mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-09-05 00:50:50 +02:00
and forcing it to be passed as an argument to all the callback functions for the search routines that require it. Magic now compiles and runs with the new code, but there are a number of known issues that need to be fixed up. Committing now so that I can rebase on the last update to the master branch.
559 lines
17 KiB
C
559 lines
17 KiB
C
/*
|
|
* PlowWidth.c --
|
|
*
|
|
* Plowing.
|
|
* Determine the true minimum width of a piece of geometry.
|
|
*
|
|
* *********************************************************************
|
|
* * 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/PlowWidth.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "utils/magic.h"
|
|
#include "utils/geometry.h"
|
|
#include "tiles/tile.h"
|
|
#include "utils/hash.h"
|
|
#include "database/database.h"
|
|
#include "plow/plowInt.h"
|
|
|
|
struct wclip
|
|
{
|
|
Edge *wc_edge; /* Initial edge */
|
|
Rect wc_area; /* Area being clipped repeatedly */
|
|
};
|
|
|
|
int plowInitWidthFunc(), plowWidthFunc();
|
|
int plowInitWidthBackFunc(), plowWidthBackFunc();
|
|
|
|
#ifdef COUNTWIDTHCALLS
|
|
int plowWidthNumCalls = 0;
|
|
int plowWidthNumChoices = 0;
|
|
#endif /* COUNTWIDTHCALLS */
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowFindWidth --
|
|
*
|
|
* Find the minimum width of material consisting of those types in the
|
|
* TileTypeBitMask 'types', starting the search from the Edge 'edge'.
|
|
*
|
|
* Results:
|
|
* Returns the minimum width.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
plowFindWidth(
|
|
Edge *edge, /* Edge along the LHS of this material */
|
|
const TileTypeBitMask *typesp,/* Types whose width is being computed.
|
|
*/
|
|
Rect *bbox, /* Bounding box of the cell */
|
|
Rect *prect) /* (Debugging only): if this is non-NULL,
|
|
* the rectangle it points to is filled
|
|
* in with the rectangle found by this
|
|
* algorithm to be the largest containing
|
|
* the edge 'edge' with only types in the
|
|
* set 'types'.
|
|
*/
|
|
{
|
|
TileTypeBitMask types = *typesp; /* TTMaskCopy(&types, typesp); */
|
|
Plane *plane = plowYankDef->cd_planes[edge->e_pNum];
|
|
TileTypeBitMask ctypes;
|
|
struct wclip wc;
|
|
int x, y;
|
|
|
|
TTMaskCom2(&ctypes, &types);
|
|
#ifdef COUNTWIDTHCALLS
|
|
plowWidthNumCalls++;
|
|
#endif /* COUNTWIDTHCALLS */
|
|
|
|
/*
|
|
* Start with wc.wc_area extending from the edge rightward to the
|
|
* cell boundary. Search right to find some tile (not necessarily
|
|
* the leftmost) that is not one of 'types'. This provides an
|
|
* upper bound on the minimum width, which we use to set wa.wa_area
|
|
* for the next loop.
|
|
*/
|
|
wc.wc_edge = edge;
|
|
wc.wc_area.r_xtop = bbox->r_xtop + 1;
|
|
wc.wc_area.r_xbot = edge->e_x;
|
|
wc.wc_area.r_ybot = edge->e_ybot;
|
|
wc.wc_area.r_ytop = edge->e_ytop;
|
|
#ifdef DEBUGWIDTH
|
|
TxPrintf("Initial area: X: %d .. %d Y: %d .. %d\n",
|
|
wc.wc_area.r_xbot, wc.wc_area.r_xtop,
|
|
wc.wc_area.r_ybot, wc.wc_area.r_ytop);
|
|
#endif /* DEBUGWIDTH */
|
|
(void) DBSrPaintArea((Tile *) NULL,
|
|
plane, &wc.wc_area, &ctypes,
|
|
plowInitWidthFunc, (ClientData) &wc);
|
|
#ifdef DEBUGWIDTH
|
|
TxPrintf("After first search, area: X: %d .. %d Y: %d .. %d\n",
|
|
wc.wc_area.r_xbot, wc.wc_area.r_xtop,
|
|
wc.wc_area.r_ybot, wc.wc_area.r_ytop);
|
|
#endif /* DEBUGWIDTH */
|
|
|
|
/*
|
|
* Repeatedly search wc.wc_area for tiles whose
|
|
* types are not in the set 'types'. Each time we find such a
|
|
* tile, we clip wc.wc_area so it still contains the original
|
|
* edge in its entirety, but excludes the offending tile.
|
|
* Continue until either the edge is degenerate (shouldn't
|
|
* happen!) or everything in wc_area is of types in 'types'.
|
|
*/
|
|
while (DBSrPaintArea((Tile *) NULL, plane, &wc.wc_area, &ctypes,
|
|
plowWidthFunc, (ClientData) &wc))
|
|
{
|
|
#ifdef DEBUGWIDTH
|
|
TxPrintf("Next area: X: %d .. %d Y: %d .. %d\n",
|
|
wc.wc_area.r_xbot, wc.wc_area.r_xtop,
|
|
wc.wc_area.r_ybot, wc.wc_area.r_ytop);
|
|
#endif /* DEBUGWIDTH */
|
|
if (wc.wc_area.r_xbot == wc.wc_area.r_xtop)
|
|
break;
|
|
}
|
|
|
|
if (prect) *prect = wc.wc_area;
|
|
x = wc.wc_area.r_xtop - wc.wc_area.r_xbot;
|
|
y = wc.wc_area.r_ytop - wc.wc_area.r_ybot;
|
|
#ifdef DEBUGWIDTH
|
|
TxPrintf("Width = %d\n", MIN(x, y));
|
|
#endif /* DEBUGWIDTH */
|
|
return (MIN(x, y));
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowInitWidthFunc --
|
|
*
|
|
* Called by area search to obtain an initial estimate of the minimum
|
|
* width of a wire. The argument 'tile' will be of a type not included
|
|
* in the set 'types' passed to plowFindWidth() above.
|
|
*
|
|
* We set our upper bound on minimum width to be the distance between
|
|
* wc->wc_edge and the LHS of tile. This means that the search rectangle
|
|
* wc->wc_area has to be modified as follows:
|
|
*
|
|
* wc_area.r_xtop will be (upper bound) to the right of wc_edge
|
|
* wc_area.r_ybot will be (upper bound) below the top of wc_edge
|
|
* wc_area.r_ytop will be (upper bound) above the bottom of wc_edge
|
|
*
|
|
* Results:
|
|
* Returns 1 always.
|
|
*
|
|
* Side effects:
|
|
* Modifies wc->wc_area as described above.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
plowInitWidthFunc(tile, dinfo, wc)
|
|
Tile *tile; /* Tile whose type is not among the types
|
|
* passed to plowFindWidth(), whose LHS will
|
|
* provide the right-hand boundary.
|
|
*/
|
|
TileType dinfo; /* (unused) */
|
|
struct wclip *wc; /* Contains original edge and area to clip */
|
|
{
|
|
Edge *edge = wc->wc_edge;
|
|
int upperBound = LEFT(tile) - edge->e_x;
|
|
|
|
#ifdef DEBUGWIDTH
|
|
TxPrintf("Tile type = %s, edgeHeight = %d, upperBound = %d\n",
|
|
DBTypeLongName(TiGetTypeExact(tile)), edge->e_ytop-edge->e_ybot, upperBound);
|
|
#endif /* DEBUGWIDTH */
|
|
wc->wc_area.r_ytop = MAX(edge->e_ybot + upperBound, edge->e_ytop);
|
|
wc->wc_area.r_ybot = MIN(edge->e_ytop - upperBound, edge->e_ybot);
|
|
wc->wc_area.r_xtop = LEFT(tile);
|
|
|
|
return (1);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowWidthFunc --
|
|
*
|
|
* Called by area search to update an estimate of the minimum width of
|
|
* a wire. The argument 'tile' will be of a type not included in the
|
|
* set 'types' passed to plowFindWidth() above.
|
|
*
|
|
* The basic idea is to modify wc->wc_area so it does not contain the
|
|
* area of 'tile', but still contains the entire edge wc->wc_edge.
|
|
* When 'tile' overlaps wc->wc_edge in Y, this can only be achieved
|
|
* by throwing away everything to the right of LEFT(tile). When 'tile'
|
|
* doesn't overlap wc->wc_edge in Y, there are generally two choices:
|
|
* clip away the right-hand side of wc_area, or clip away the top (or
|
|
* bottom). To avoid a combinatoric explosion, we act greedily and
|
|
* clip in such a way as to keep the largest dimension largest.
|
|
*
|
|
* Results:
|
|
* Returns 1 always.
|
|
*
|
|
* Side effects:
|
|
* Modifies wc->wc_area as described above.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
plowWidthFunc(tile, dinfo, wc)
|
|
Tile *tile; /* Tile whose type is not among the types
|
|
* passed to plowFindWidth(), which will be
|
|
* clipped out of the area wc->wc_area in
|
|
* such a way that the original edge will
|
|
* remain a part of wc->wc_area.
|
|
*/
|
|
TileType dinfo; /* (unused) */
|
|
struct wclip *wc; /* Contains original edge and area to clip */
|
|
{
|
|
Edge *edge = wc->wc_edge;
|
|
int xw, yw;
|
|
int yt, yb;
|
|
|
|
/*
|
|
* If the tile overlaps the edge in Y, we have to clip the
|
|
* RHS of the area. If clipping the RHS makes X the new
|
|
* smallest dimension, clip Y appropriately.
|
|
*/
|
|
xw = LEFT(tile) - wc->wc_area.r_xbot;
|
|
if (BOTTOM(tile) < edge->e_ytop && TOP(tile) > edge->e_ybot)
|
|
{
|
|
wc->wc_area.r_xtop = LEFT(tile);
|
|
goto clipvert;
|
|
}
|
|
|
|
/*
|
|
* If the tile is above the edge in Y, consider both
|
|
* alternatives (clipping the top, and clipping the
|
|
* right), choosing whichever one leaves us with the
|
|
* larger minimum width. This may not always work,
|
|
* but is simple.
|
|
*/
|
|
#ifdef COUNTWIDTHCALLS
|
|
plowWidthNumChoices++;
|
|
#endif /* COUNTWIDTHCALLS */
|
|
if (BOTTOM(tile) >= edge->e_ytop)
|
|
{
|
|
yw = BOTTOM(tile) - wc->wc_area.r_ybot;
|
|
if (xw >= yw)
|
|
{
|
|
wc->wc_area.r_xtop = LEFT(tile);
|
|
goto clipvert;
|
|
}
|
|
else
|
|
{
|
|
wc->wc_area.r_ytop = BOTTOM(tile);
|
|
goto clipright;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* The tile is below the edge in Y, so consider both
|
|
* alternatives (clipping the bottom, and clipping the
|
|
* right), choosing whichever one leaves us with the
|
|
* larger minimum width. This may not always work,
|
|
* but is simple.
|
|
*/
|
|
yw = wc->wc_area.r_ytop - TOP(tile);
|
|
if (xw >= yw)
|
|
{
|
|
wc->wc_area.r_xtop = LEFT(tile);
|
|
goto clipvert;
|
|
}
|
|
else
|
|
{
|
|
wc->wc_area.r_ybot = TOP(tile);
|
|
goto clipright;
|
|
}
|
|
|
|
clipvert:
|
|
yt = MIN(edge->e_ybot + xw, wc->wc_area.r_ytop);
|
|
yb = MAX(edge->e_ytop - xw, wc->wc_area.r_ybot);
|
|
if (yt > wc->wc_edge->e_ytop) wc->wc_area.r_ytop = yt;
|
|
if (yb < wc->wc_edge->e_ybot) wc->wc_area.r_ybot = yb;
|
|
return (1);
|
|
|
|
clipright:
|
|
yw = wc->wc_area.r_ytop - wc->wc_area.r_ybot;
|
|
xw = wc->wc_area.r_xtop - wc->wc_area.r_xbot;
|
|
if (yw < xw)
|
|
wc->wc_area.r_xtop = wc->wc_area.r_xbot + yw;
|
|
return (1);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowFindWidthBack --
|
|
*
|
|
* Find the minimum width of material consisting of those types in the
|
|
* TileTypeBitMask 'types', starting the search from the Edge 'edge',
|
|
* but searching to the left instead of to the right.
|
|
*
|
|
* Results:
|
|
* Returns the minimum width.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
plowFindWidthBack(
|
|
Edge *edge, /* Edge along the RHS of this material */
|
|
const TileTypeBitMask *typesp,/* Types whose width is being computed.
|
|
*/
|
|
Rect *bbox, /* Bounding box of the cell */
|
|
Rect *prect) /* (Debugging only): if this is non-NULL,
|
|
* the rectangle it points to is filled
|
|
* in with the rectangle found by this
|
|
* algorithm to be the largest containing
|
|
* the edge 'edge' with only types in the
|
|
* set 'types'.
|
|
*/
|
|
{
|
|
TileTypeBitMask types = *typesp; /* TTMaskCopy(&types, typesp); */
|
|
Plane *plane = plowYankDef->cd_planes[edge->e_pNum];
|
|
TileTypeBitMask ctypes;
|
|
struct wclip wc;
|
|
int x, y;
|
|
|
|
TTMaskCom2(&ctypes, &types);
|
|
|
|
/*
|
|
* Start with wc.wc_area extending from the edge rightward to the
|
|
* cell boundary. Search left to find some tile (not necessarily
|
|
* the rightmost) that is not one of 'types'. This provides an
|
|
* upper bound on the minimum width, which we use to set wa.wa_area
|
|
* for the next loop.
|
|
*/
|
|
wc.wc_edge = edge;
|
|
wc.wc_area.r_xtop = edge->e_x;
|
|
wc.wc_area.r_xbot = bbox->r_xbot - 1;
|
|
wc.wc_area.r_ybot = edge->e_ybot;
|
|
wc.wc_area.r_ytop = edge->e_ytop;
|
|
#ifdef DEBUGWIDTH
|
|
TxPrintf("Initial area: X: %d .. %d Y: %d .. %d\n",
|
|
wc.wc_area.r_xbot, wc.wc_area.r_xtop,
|
|
wc.wc_area.r_ybot, wc.wc_area.r_ytop);
|
|
#endif /* DEBUGWIDTH */
|
|
(void) DBSrPaintArea((Tile *) NULL,
|
|
plane, &wc.wc_area, &ctypes,
|
|
plowInitWidthBackFunc, (ClientData) &wc);
|
|
#ifdef DEBUGWIDTH
|
|
TxPrintf("After first search, area: X: %d .. %d Y: %d .. %d\n",
|
|
wc.wc_area.r_xbot, wc.wc_area.r_xtop,
|
|
wc.wc_area.r_ybot, wc.wc_area.r_ytop);
|
|
#endif /* DEBUGWIDTH */
|
|
|
|
/*
|
|
* Repeatedly search wc.wc_area for tiles whose
|
|
* types are not in the set 'types'. Each time we find such a
|
|
* tile, we clip wc.wc_area so it still contains the original
|
|
* edge in its entirety, but excludes the offending tile.
|
|
* Continue until either the edge is degenerate (shouldn't
|
|
* happen!) or everything in wc_area is of types in 'types'.
|
|
*/
|
|
while (DBSrPaintArea((Tile *) NULL, plane, &wc.wc_area, &ctypes,
|
|
plowWidthBackFunc, (ClientData) &wc))
|
|
{
|
|
#ifdef DEBUGWIDTH
|
|
TxPrintf("Next area: X: %d .. %d Y: %d .. %d\n",
|
|
wc.wc_area.r_xbot, wc.wc_area.r_xtop,
|
|
wc.wc_area.r_ybot, wc.wc_area.r_ytop);
|
|
#endif /* DEBUGWIDTH */
|
|
if (wc.wc_area.r_xbot == wc.wc_area.r_xtop)
|
|
break;
|
|
}
|
|
|
|
if (prect) *prect = wc.wc_area;
|
|
x = wc.wc_area.r_xtop - wc.wc_area.r_xbot;
|
|
y = wc.wc_area.r_ytop - wc.wc_area.r_ybot;
|
|
#ifdef DEBUGWIDTH
|
|
TxPrintf("Width = %d\n", MIN(x, y));
|
|
#endif /* DEBUGWIDTH */
|
|
return (MIN(x, y));
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowInitWidthBackFunc --
|
|
*
|
|
* Called by area search to obtain an initial estimate of the minimum
|
|
* width of a wire. The argument 'tile' will be of a type not included
|
|
* in the set 'types' passed to plowFindWidth() above.
|
|
*
|
|
* We set our upper bound on minimum width to be the distance between
|
|
* wc->wc_edge and the RHS of tile. This means that the search rectangle
|
|
* wc->wc_area has to be modified as follows:
|
|
*
|
|
* wc_area.r_xbot will be (upper bound) to the left of wc_edge
|
|
* wc_area.r_ybot will be (upper bound) below the top of wc_edge
|
|
* wc_area.r_ytop will be (upper bound) above the bottom of wc_edge
|
|
*
|
|
* Results:
|
|
* Returns 1 always.
|
|
*
|
|
* Side effects:
|
|
* Modifies wc->wc_area as described above.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
plowInitWidthBackFunc(tile, dinfo, wc)
|
|
Tile *tile; /* Tile whose type is not among the types
|
|
* passed to plowFindWidthBack(), whose RHS will
|
|
* provide the left-hand boundary.
|
|
*/
|
|
TileType dinfo; /* (unused) */
|
|
struct wclip *wc; /* Contains original edge and area to clip */
|
|
{
|
|
Edge *edge = wc->wc_edge;
|
|
int upperBound = edge->e_x - RIGHT(tile);
|
|
|
|
#ifdef DEBUGWIDTH
|
|
TxPrintf("Tile type = %s, edgeHeight = %d, upperBound = %d\n",
|
|
DBTypeLongName(TiGetTypeExact(tile)), edge->e_ytop-edge->e_ybot, upperBound);
|
|
#endif /* DEBUGWIDTH */
|
|
wc->wc_area.r_ytop = MAX(edge->e_ybot + upperBound, edge->e_ytop);
|
|
wc->wc_area.r_ybot = MIN(edge->e_ytop - upperBound, edge->e_ybot);
|
|
wc->wc_area.r_xbot = RIGHT(tile);
|
|
|
|
return (1);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* plowWidthBackFunc --
|
|
*
|
|
* Called by area search to update an estimate of the minimum width of
|
|
* a wire. The argument 'tile' will be of a type not included in the
|
|
* set 'types' passed to plowFindWidth() above.
|
|
*
|
|
* The basic idea is to modify wc->wc_area so it does not contain the
|
|
* area of 'tile', but still contains the entire edge wc->wc_edge.
|
|
* When 'tile' overlaps wc->wc_edge in Y, this can only be achieved
|
|
* by throwing away everything to the left of RIGHT(tile). When 'tile'
|
|
* doesn't overlap wc->wc_edge in Y, there are generally two choices:
|
|
* clip away the left-hand side of wc_area, or clip away the top (or
|
|
* bottom). To avoid a combinatoric explosion, we act greedily and
|
|
* clip in such a way as to keep the largest dimension largest.
|
|
*
|
|
* Results:
|
|
* Returns 1 always.
|
|
*
|
|
* Side effects:
|
|
* Modifies wc->wc_area as described above.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
plowWidthBackFunc(tile, dinfo, wc)
|
|
Tile *tile; /* Tile whose type is not among the types
|
|
* passed to plowFindWidth(), which will be
|
|
* clipped out of the area wc->wc_area in
|
|
* such a way that the original edge will
|
|
* remain a part of wc->wc_area.
|
|
*/
|
|
TileType dinfo; /* (unused) */
|
|
struct wclip *wc; /* Contains original edge and area to clip */
|
|
{
|
|
Edge *edge = wc->wc_edge;
|
|
int xw, yw;
|
|
int yt, yb;
|
|
|
|
/*
|
|
* If the tile overlaps the edge in Y, we have to clip the
|
|
* LHS of the area. If clipping the LHS makes X the new
|
|
* smallest dimension, clip Y appropriately.
|
|
*/
|
|
xw = wc->wc_area.r_xtop - RIGHT(tile);
|
|
if (BOTTOM(tile) < edge->e_ytop && TOP(tile) > edge->e_ybot)
|
|
{
|
|
wc->wc_area.r_xbot = RIGHT(tile);
|
|
goto clipvert;
|
|
}
|
|
|
|
/*
|
|
* If the tile is above the edge in Y, consider both
|
|
* alternatives (clipping the top, and clipping the
|
|
* right), choosing whichever one leaves us with the
|
|
* larger minimum width. This may not always work,
|
|
* but is simple.
|
|
*/
|
|
if (BOTTOM(tile) >= edge->e_ytop)
|
|
{
|
|
yw = BOTTOM(tile) - wc->wc_area.r_ybot;
|
|
if (xw >= yw)
|
|
{
|
|
wc->wc_area.r_xbot = RIGHT(tile);
|
|
goto clipvert;
|
|
}
|
|
else
|
|
{
|
|
wc->wc_area.r_ytop = BOTTOM(tile);
|
|
goto clipright;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* The tile is below the edge in Y, so consider both
|
|
* alternatives (clipping the bottom, and clipping the
|
|
* right), choosing whichever one leaves us with the
|
|
* larger minimum width. This may not always work,
|
|
* but is simple.
|
|
*/
|
|
yw = wc->wc_area.r_ytop - TOP(tile);
|
|
if (xw >= yw)
|
|
{
|
|
wc->wc_area.r_xbot = RIGHT(tile);
|
|
goto clipvert;
|
|
}
|
|
else
|
|
{
|
|
wc->wc_area.r_ybot = TOP(tile);
|
|
goto clipright;
|
|
}
|
|
|
|
clipvert:
|
|
yt = MIN(edge->e_ybot + xw, wc->wc_area.r_ytop);
|
|
yb = MAX(edge->e_ytop - xw, wc->wc_area.r_ybot);
|
|
if (yt > wc->wc_edge->e_ytop) wc->wc_area.r_ytop = yt;
|
|
if (yb < wc->wc_edge->e_ybot) wc->wc_area.r_ybot = yb;
|
|
return (1);
|
|
|
|
clipright:
|
|
yw = wc->wc_area.r_ytop - wc->wc_area.r_ybot;
|
|
xw = wc->wc_area.r_xtop - wc->wc_area.r_xbot;
|
|
if (yw < xw)
|
|
wc->wc_area.r_xbot = wc->wc_area.r_xtop - yw;
|
|
return (1);
|
|
}
|