home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
deans.zip
/
BASE.CPP
next >
Wrap
C/C++ Source or Header
|
1994-09-03
|
45KB
|
1,633 lines
//
// NAME: CIDLib_Base.Cpp
//
// DESCRIPTION:
//
// This module implements a number of simple classes that provide workhorse
// types. None of these involve any system resources or anything like that.
//
//
// AUTHOR: Dean Roddey
//
// CREATE DATE: 05/23/93
//
// COPYRIGHT: 1992..1994, 'CIDCorp
//
// CAVEATS/GOTCHAS:
//
// MODIFICATION LOG:
//
// -----------------------------------------------------------------------------
// Local defines
// -----------------------------------------------------------------------------
#define CIDGUI_BASE_CPP
#define INCL_CIDGUI_ERRORIDS
#define INCL_CIDGUI_FACOBJECT
// -----------------------------------------------------------------------------
// Facility specific includes
// -----------------------------------------------------------------------------
#include "CIDGui_.Hpp"
// -----------------------------------------------------------------------------
// CLASS: AREA
// PREFIX: area
//
// This class defines a rectangular area
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// AREA: Constructor and Destructor
// -----------------------------------------------------------------------------
//
// FUNCTION/METHOD NAME: AREA()
// AREA(i4X, i4Y, c4CX, c4CY)
// AREA(rectlSrc, eInclusive)
// AREA(ptlLLeft, ptlURt)
// AREA(pntLLeft, pntURt)
// AREA(swpSrc)
//
// DESCRIPTION:
//
// This constructor will create an area from various components.
// ---------------------------------------
// INPUT: i4X, i4Y, c4CX, c4CY are the origin and size to contruct from
// rectlSrc is the source rectangle to construct from
// ptlLLeft, ptlURt are two POINTLs to construct from
// pntLLeft, pntURt are two POINT objects to construct from
// eInclusive indicates whether the rectangle is inclusive or not.
//
// OUTPUT: None
//
// RETURN: None
//
PROCEXP AREA::AREA(const RECTL& rectlSrc, tCIDGui::eRECTLTYPE eInclusive) :
__i4X(MinVal(rectlSrc.xLeft, rectlSrc.xRight))
, __i4Y(MinVal(rectlSrc.yBottom, rectlSrc.yTop))
, __c4CX(rectlSrc.xLeft > rectlSrc.xRight ?
rectlSrc.xLeft-rectlSrc.xRight :
rectlSrc.xRight-rectlSrc.xLeft)
, __c4CY(rectlSrc.yBottom > rectlSrc.yTop ?
rectlSrc.yTop - rectlSrc.yBottom :
rectlSrc.yTop-rectlSrc.yBottom)
{
if (eInclusive == tCIDGui::eRECTL_INCLUSIVE)
{
// Be careful of an empty rectangle
if (__c4CX)
__c4CX++;
if (__c4CY)
__c4CY++;
}
}
PROCEXP AREA::AREA(const POINTL& ptlLLeft, const POINTL& ptlURt) :
__i4X(MinVal(ptlLLeft.x, ptlURt.x))
, __c4CX(ptlLLeft.x > ptlURt.x ? ptlLLeft.x-ptlURt.x : ptlURt.x-ptlLLeft.x)
, __i4Y(MinVal(ptlLLeft.y, ptlURt.y))
, __c4CY(ptlLLeft.y > ptlURt.y ? ptlLLeft.y-ptlURt.y : ptlURt.y-ptlLLeft.y)
{
// Bump up the sizes to make them right
__c4CX++;
__c4CY++;
}
PROCEXP AREA::AREA(const POINT& pntLLeft, const POINT& pntURt)
{
// Get the values out of the points for greater efficiency
tCIDLib::INT4 i4X1 = pntLLeft.i4X();
tCIDLib::INT4 i4Y1 = pntLLeft.i4Y();
tCIDLib::INT4 i4X2 = pntURt.i4X();
tCIDLib::INT4 i4Y2 = pntURt.i4Y();
__i4X = MinVal(i4X1, i4X2);
__c4CX = i4X1 > i4X2 ? i4X1-i4X2 : i4X2-i4X1;
__i4Y = MinVal(i4Y1, i4Y2);
__c4CY = i4Y1 > i4Y2 ? i4Y1-i4Y2 : i4Y2-i4Y1;
// Bump up the sizes to make them right
__c4CX++;
__c4CY++;
}
PROCEXP AREA::AREA(const SWP& swpSrc) :
__i4X(swpSrc.x)
, __c4CX(swpSrc.cx)
, __i4Y(swpSrc.y)
, __c4CY(swpSrc.cy)
{
}
PROCEXP AREA::AREA( tCIDLib::INT4 x
, tCIDLib::INT4 y
, tCIDLib::CARD4 cx
, tCIDLib::CARD4 cy) :
__i4X(x)
, __i4Y(y)
, __c4CX(cx)
, __c4CY(cy)
{
}
PROCEXP AREA::AREA() :
__i4X(0)
, __i4Y(0)
, __c4CX(0)
, __c4CY(0)
{
}
PROCEXP AREA::AREA(const AREA& areaSrc) :
__i4X(areaSrc.__i4X)
, __i4Y(areaSrc.__i4Y)
, __c4CX(areaSrc.__c4CX)
, __c4CY(areaSrc.__c4CY)
{
}
// -----------------------------------------------------------------------------
// AREA: Public, inherited methods
// -----------------------------------------------------------------------------
//
// FUNCTION/METHOD NAME: FormatAt(pszBuf, c4CurInd);
//
// DESCRIPTION:
//
// This message is called to format this class' members into the passed
// buffer.
// ---------------------------------------
// INPUT: pszBuf is a pointer to the buffer to format into
// c4CurInd is the index at which this class should start formatting.
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::FormatAt( tCIDLib::CH* pszBuf
, tCIDLib::CARD4& c4CurInd) const
{
tCIDLib::CH* pszTmp;
tCIDLib::CH* pszStart;
// Call our parent's version
CIDSTORABLE::FormatAt(pszBuf, c4CurInd);
//
// Address our starting position in the buffer and remember where we
// started.
//
pszTmp = &pszBuf[c4CurInd];
pszStart = pszTmp;
// Write out the origin and size information
*(tCIDLib::INT4*)pszTmp = __i4X;
pszTmp += sizeof(__i4X);
*(tCIDLib::INT4*)pszTmp = __i4Y;
pszTmp += sizeof(__i4Y);
*(tCIDLib::CARD4*)pszTmp = __c4CX;
pszTmp += sizeof(__c4CX);
*(tCIDLib::CARD4*)pszTmp = __c4CY;
pszTmp += sizeof(__c4CY);
// Bump up cCurInd by the bytes we used
c4CurInd += tCIDLib::CARD4(pszTmp-pszStart);
}
//
// FUNCTION/METHOD NAME: FormatToStr(strbDest) const
//
// DESCRIPTION:
//
// This method will format the data members into the passed string buffer
// ---------------------------------------
// INPUT: None
//
// OUTPUT: strbDest is the buffer to format into
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::FormatToStr(STRGBUF& strbDest) const
{
strbDest << "X=" << __i4X << ",Y=" << __i4Y;
strbDest << ",cX=" << __c4CX << ",cY=" << __c4CY;
}
//
// FUNCTION/METHOD NAME: ParseAt(pszBuf, c4CurInd)
//
// DESCRIPTION:
//
// This method will parse the data from the passed buffer into this object.
// We first call our parent class, then parse out our data members.
// ---------------------------------------
// INPUT: pszBuf is the buffer to parse from.
// c4CurInd is where we start parsing from.
//
// OUTPUT: c4CurInd is bumped up by the number of bytes parsed at this
// level and all below us
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::ParseAt(const tCIDLib::CH* pszBuf
, tCIDLib::CARD4& c4CurInd)
{
// Call our parent's version
CIDSTORABLE::ParseAt(pszBuf, c4CurInd);
//
// Address our starting position in the buffer and remember where we
// started.
//
const tCIDLib::CH* pszTmp = &pszBuf[c4CurInd];
const tCIDLib::CH* pszStart = pszTmp;
// Get the origin and size values
__i4X = *(tCIDLib::INT4*)pszTmp;
pszTmp += sizeof(__i4X);
__i4Y = *(tCIDLib::INT4*)pszTmp;
pszTmp += sizeof(__i4Y);
__c4CX = *(tCIDLib::CARD4*)pszTmp;
pszTmp += sizeof(__c4CX);
__c4CY = *(tCIDLib::CARD4*)pszTmp;
pszTmp += sizeof(__c4CY);
// Bump up cCurInd by the bytes we used
c4CurInd += tCIDLib::CARD4(pszTmp-pszStart);
}
// -----------------------------------------------------------------------------
// AREA: Public, non-virtual methods
// -----------------------------------------------------------------------------
//
// FUNCTION/METHOD NAME: operator+(areaSrc)
// operator+=(areaSrc)
//
// DESCRIPTION:
//
// This method will add two areas, creating a union of the two and leaving
// the result in this object.
// ---------------------------------------
// INPUT: areaSrc is the area to add
//
// OUTPUT: None
//
// RETURN: A reference to this object for += or a new AREA object for +.
//
AREA AREA::operator+(const AREA& areaSrc)
{
tCIDLib::CARD4 c4CX, c4CY;
tCIDLib::INT4 i4X, i4Y;
// If the same object, then return a copy of this object
if (&areaSrc == this)
return *this;
i4X = MinVal(areaSrc.__i4X, __i4X);
i4Y = MinVal(areaSrc.__i4Y, __i4Y);
c4CX = MaxVal(areaSrc.i4XRight(), i4XRight()) - i4X;
c4CY = MaxVal(areaSrc.i4YTop(), i4YTop()) - i4Y;
return AREA(i4X, i4Y, c4CX, c4CY);
}
tCIDLib::VOID AREA::operator+=(const AREA& areaSrc)
{
tCIDLib::CARD4 c4CX, c4CY;
tCIDLib::INT4 i4X, i4Y;
// If the same object, then nothing to do
if (&areaSrc == this)
return;
i4X = MinVal(areaSrc.__i4X, __i4X);
i4Y = MinVal(areaSrc.__i4Y, __i4Y);
c4CX = MaxVal(areaSrc.i4XRight(), i4XRight()) - i4X;
c4CY = MaxVal(areaSrc.i4YTop(), i4YTop()) - i4Y;
__i4X = i4X;
__i4Y = i4Y;
__c4CX = c4CX;
__c4CY = c4CY;
}
//
// FUNCTION/METHOD NAME: operator-(areaSrc)
// operator-=(areaSrc)
//
// DESCRIPTION:
//
// This method will add subtract two areas, creating an area that is the
// intersection of the two areas. If they just touch on a side, this is not
// overlapping
// ---------------------------------------
// INPUT: areaSrc is the area to intersect with this object.
//
// OUTPUT: None
//
// RETURN: A reference to this object for -= or a new AREA object for -.
//
AREA PROCEXP AREA::operator-(const AREA& areaSrc)
{
// If the same object, then return a copy of this object
if (&areaSrc == this)
return *this;
// Check for no intersection
if (areaSrc.i4XRight() <= __i4X)
return AREA(0,0,0,0);
if (i4XRight() <= areaSrc.__i4X)
return AREA(0,0,0,0);
if (areaSrc.i4YTop() <= __i4Y)
return AREA(0,0,0,0);
if (i4YTop() <= areaSrc.__i4Y)
return AREA(0,0,0,0);
//
// Check for identical position and size. Then just return a copy of
// this rectangle.
//
if ((areaSrc.__i4X == __i4X)
&& (areaSrc.__i4Y == __i4Y)
&& (areaSrc.__c4CX == __c4CX)
&& (areaSrc.__c4CY == __c4CY))
{
return *this;
}
//
// They intersect, so we need to find the one with the lower origin.
// It's upper right corner becomes the upper right of the result. The
// other one's lower left corner becomes the lower left.
//
if (areaSrc.__i4X < __i4X)
{
return AREA(__i4X
, __i4Y
, areaSrc.i4XRight()-__i4X
, areaSrc.i4YTop()-__i4Y);
}
return AREA(areaSrc.__i4X
, areaSrc.__i4Y
, i4XRight()-areaSrc.__i4X
, i4YTop()-areaSrc.__i4Y);
}
tCIDLib::VOID PROCEXP AREA::operator-=(const AREA& areaSrc)
{
// If the same object, then return
if (&areaSrc == this)
return;
//
// Check for identical position and size. If so just return
//
if ((areaSrc.__i4X == __i4X)
&& (areaSrc.__i4Y == __i4Y)
&& (areaSrc.__c4CX == __c4CX)
&& (areaSrc.__c4CY == __c4CY))
{
return;
}
// Set this area to empty as a default
__i4X = 0;
__i4Y = 0;
__c4CX = 0;
__c4CY = 0;
// Check for no intersection
if (areaSrc.i4XRight() <= __i4X)
return;
if (i4XRight() <= areaSrc.__i4X)
return;
if (areaSrc.i4YTop() <= __i4Y)
return;
if (i4YTop() <= areaSrc.__i4Y)
return;
//
// They intersect, so we need to find the one with the lower origin.
// It's upper right corner becomes the upper right of the result. The
// other one's lower left corner becomes the lower left.
//
if (areaSrc.__i4X < __i4X)
{
__c4CX = areaSrc.i4XRight()-__i4X;
__c4CY = areaSrc.i4YTop()-__i4Y;
}
else
{
__i4X = areaSrc.__i4Y;
__i4Y = areaSrc.__i4Y;
__c4CX = i4XRight()-areaSrc.__i4X;
__c4CY = i4YTop()-areaSrc.__i4Y;
}
}
//
// FUNCTION/METHOD NAME: AdjustOrg(i4XOfs, i4YOfs)
// AdjustOrg(pntOfs)
//
// DESCRIPTION:
//
// This method will adjust the origin of the area by the passed offsets.
// ---------------------------------------
// INPUT: i4XOfs, i4YOfs are the offsets
// pntOfs provides both offsets at once
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::AdjustOrg( tCIDLib::INT4 i4XOfs
, tCIDLib::INT4 i4YOfs)
{
__i4X += i4XOfs;
__i4Y += i4YOfs;
}
tCIDLib::VOID PROCEXP AREA::AdjustOrg(const POINT& pntOfs)
{
__i4X += pntOfs.i4X();
__i4Y += pntOfs.i4Y();
}
//
// FUNCTION/METHOD NAME: AdjustSides(i4XOfs, i4YOfs)
//
// DESCRIPTION:
//
// This method will adjust the sides of the area by the given x and y
// offsets. Negative values will cause the area to become smaller and
// positive values will cause it to become larger. Both sides are pushed
// outward or inward by the offset amount.
// ---------------------------------------
// INPUT: i4XOfs, i4YOfs are the offsets to adjust the sides by
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::AdjustSides(tCIDLib::INT4 i4XOfs
, tCIDLib::INT4 i4YOfs)
{
tCIDLib::eBOOL bNegX, bNegY;
//
// If the x offset is negative, then see if the area is large enough to
// adjust by this offset. If not, then set the offset to the best we can
// do, which is to make it a 0 sized area with a new origin that is at
// the middle of the old size. Do the same thing for the y offset also.
//
if (i4XOfs < 0)
{
bNegX = tCIDLib::eTRUE;
i4XOfs *= -1;
}
else
{
bNegX = tCIDLib::eFALSE;
}
if ((i4XOfs << 1) >= __c4CX)
i4XOfs = tCIDLib::INT4(__c4CX >> 1);
if (i4YOfs < 0)
{
bNegY = tCIDLib::eTRUE;
i4YOfs *= -1;
}
else
{
bNegY = tCIDLib::eFALSE;
}
if ((i4YOfs << 1) >= __c4CY)
i4YOfs = tCIDLib::INT4(__c4CY >> 1);
//
// Now adjust the sides. Adjust the orgin first, then adjust the length
// and width. When doing the length and width, be careful to check for
// a potential underflow of the __c4CX and __c4CY values. Despite the
// checks done above, the offset may have been an odd number, in which
// case there could still be an overflow of 1. The division done above
// was via a shift operation, which would just truncate the extra odd
// bit.
//
if (bNegX)
{
__i4X += i4XOfs;
if (__c4CX <= i4XOfs * 2)
__c4CX = 0;
else
__c4CX -= (i4XOfs * 2);
}
else
{
__i4X -= i4XOfs;
__c4CX += (i4XOfs * 2);
}
if (bNegY)
{
__i4Y += i4YOfs;
if (__c4CY <= i4YOfs * 2)
__c4CY = 0;
else
__c4CY -= (i4YOfs * 2);
}
else
{
__i4Y -= i4YOfs;
__c4CY += (i4YOfs * 2);
}
}
//
// FUNCTION/METHOD NAME: AdjustSize(i4CXOfs, i4CYOfs)
//
// DESCRIPTION:
//
// This method will adjust the cx and cy values of the area by the passed
// values. Trying to size an area below 0 length is an error.
// ---------------------------------------
// INPUT: i4CXOfs, i4CYOfs are the offsets to apply to the current area size.
// They should be negative to make the size smaller, or positive
// to make it larger.
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::AdjustSize( tCIDLib::INT4 i4CXOfs
, tCIDLib::INT4 i4CYOfs)
{
tCIDLib::CARD4 c4AbsCXOfs = i4CXOfs < 0 ? i4CXOfs * -1 : i4CXOfs;
tCIDLib::CARD4 c4AbsCYOfs = i4CYOfs < 0 ? i4CYOfs * -1 : i4CYOfs;
// Check for underflows first
if (c4AbsCXOfs > __c4CX)
{
facCIDGui.LogErr( __FILE__
, "AREA::AdjustSize"
, __LINE__
, GUIERR_COORD_AREA_UNDERFLOW
, "(Horizontal)"
, tCIDLib::eSEV_PROCESS_FATAL
, tCIDLib::eCLASS_BADPARMS
, INTEGER(i4CXOfs)
, CARDINAL(__c4CX));
}
if (c4AbsCYOfs > __c4CY)
{
facCIDGui.LogErr( __FILE__
, "AREA::AdjustSize"
, __LINE__
, GUIERR_COORD_AREA_UNDERFLOW
, "(Vertical)"
, tCIDLib::eSEV_PROCESS_FATAL
, tCIDLib::eCLASS_BADPARMS
, INTEGER(i4CYOfs)
, CARDINAL(__c4CY));
}
// Go ahead and modify the size
__c4CX += i4CXOfs;
__c4CY += i4CYOfs;
}
//
// FUNCTION/METHOD NAME: areaHorzPercent(c4Percent) const
// areaVertPercent(c4Percent) const
//
// DESCRIPTION:
//
// These methods will return areas that represent percentages of this area.
// The indicated direction is the one that is calculated and the other is left
// at the full size of this area.
// ---------------------------------------
// INPUT: c4Percent is percent of the area to calculate
//
// OUTPUT: None
//
// RETURN: The percentage area
//
AREA PROCEXP AREA::areaHorzPercent(tCIDLib::CARD4 c4Percent) const
{
if (c4Percent > 100)
{
facCIDGui.LogErr( __FILE__
, "AREA::areaHorzPercent"
, __LINE__
, GUIERR_GEN_PERCENT_RANGE
, tCIDLib::eSEV_PROCESS_FATAL
, tCIDLib::eCLASS_BADPARMS
, CARDINAL(c4Percent));
}
if (!c4Percent)
return AREA(__i4X, __i4Y, 0, 0);
tCIDLib::FLOAT4 f4Per = tCIDLib::FLOAT4(c4Percent) / 100.0;
return AREA(__i4X, __i4Y, tCIDLib::CARD4(__c4CX * f4Per), __c4CY);
}
AREA PROCEXP AREA::areaVertPercent(tCIDLib::CARD4 c4Percent) const
{
if (c4Percent > 100)
{
facCIDGui.LogErr( __FILE__
, "AREA::areaVertPercent"
, __LINE__
, GUIERR_GEN_PERCENT_RANGE
, tCIDLib::eSEV_PROCESS_FATAL
, tCIDLib::eCLASS_BADPARMS
, CARDINAL(c4Percent));
}
if (!c4Percent)
return AREA(__i4X, __i4Y, 0, 0);
tCIDLib::FLOAT4 f4Per = tCIDLib::FLOAT4(c4Percent) / 100.0;
return AREA(__i4X, __i4Y, __c4CX, tCIDLib::CARD4(__c4CY * f4Per));
}
//
// FUNCTION/METHOD NAME: bEmpty() const
//
// DESCRIPTION:
//
// This method will return eTRUE if either the cx or cy is 0.
// ---------------------------------------
// INPUT: None
//
// OUTPUT: None
//
// RETURN: eTRUE if the area is empty, else eFALSE
//
tCIDLib::eBOOL PROCEXP AREA::bEmpty() const
{
return (!__c4CX || !__c4CY) ? tCIDLib::eTRUE : tCIDLib::eFALSE;
}
//
// FUNCTION/METHOD NAME: bIntersects(areaTest) const
//
// DESCRIPTION:
//
// This method will see if this area intersects the passed one.
// ---------------------------------------
// INPUT: areaTest is the area to test this area agaisnt for intersection.
//
// OUTPUT: None
//
// RETURN: eTRUE if the areas intersect, else eFALSE.
//
tCIDLib::eBOOL PROCEXP AREA::bIntersects(const AREA& areaTest) const
{
// If either is empty, then cannot intersect
if (bEmpty() || areaTest.bEmpty())
return tCIDLib::eFALSE;
// Get the upper extremes of each area
tCIDLib::INT4 i4ThisXRight = i4XRight();
tCIDLib::INT4 i4ThisYTop = i4YTop();
tCIDLib::INT4 i4TestXRight = areaTest.i4XRight();
tCIDLib::INT4 i4TestYTop = areaTest.i4YTop();
// Check the sides
if (areaTest.__i4X > i4ThisXRight)
return tCIDLib::eFALSE;
if (__i4X > i4TestXRight)
return tCIDLib::eFALSE;
if (areaTest.__i4Y > i4ThisYTop)
return tCIDLib::eFALSE;
if (__i4Y > i4TestYTop)
return tCIDLib::eFALSE;
// They intersect
return tCIDLib::eTRUE;
}
//
// FUNCTION/METHOD NAME: FromPnts(pntLLeft, pntlURight)
//
// DESCRIPTION:
//
// This will convert the two passed points, which represent the lower left and
// upper right corners of a rectangle, into an area.
//
// NOTE: The points may be rearranged if the lower left point is actually
// greater than the upper right.
// ---------------------------------------
// INPUT: pntLLeft, pntURight are the two points that define the area.
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::FromPnts( const POINT& pntLLeft
, const POINT& pntURight)
{
if (pntLLeft.i4X() > pntURight.i4X())
{
__i4X = pntURight.i4X();
__c4CX = (pntLLeft.i4X()-pntURight.i4X()) + 1;
}
else
{
__i4X = pntLLeft.i4X();
__c4CX = (pntURight.i4X()-pntLLeft.i4X()) + 1;
}
if (pntLLeft.i4Y() > pntURight.i4Y())
{
__i4Y = pntURight.i4Y();
__c4CY = (pntLLeft.i4Y()-pntURight.i4Y()) + 1;
}
else
{
__i4Y = pntLLeft.i4Y();
__c4CY = (pntURight.i4Y()-pntLLeft.i4Y()) + 1;
}
}
//
// FUNCTION/METHOD NAME: FromPtls(ptlLLeft, ptlURight)
//
// DESCRIPTION:
//
// This will convert the two passed points, which represent the lower left and
// upper right corners of a rectangle, into an area.
//
// NOTE: The points may be rearranged if the lower left point is actually
// greater than the upper right.
// ---------------------------------------
// INPUT: ptlLLeft, ptlURight are the two points that define the area.
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::FromPtls( const POINTL& ptlLLeft
, const POINTL& ptlURight)
{
if (ptlLLeft.x > ptlURight.x)
{
__i4X = tCIDLib::CARD4(ptlURight.x);
__c4CX = tCIDLib::CARD4(ptlLLeft.x-ptlURight.x)+1;
}
else
{
__i4X = tCIDLib::CARD4(ptlLLeft.x);
__c4CX = tCIDLib::CARD4(ptlURight.x-ptlLLeft.x)+1;
}
if (ptlLLeft.y > ptlURight.y)
{
__i4Y = tCIDLib::CARD4(ptlURight.y);
__c4CY = tCIDLib::CARD4(ptlLLeft.y-ptlURight.y)+1;
}
else
{
__i4Y = tCIDLib::CARD4(ptlLLeft.y);
__c4CY = tCIDLib::CARD4(ptlURight.y-ptlLLeft.y)+1;
}
}
//
// FUNCTION/METHOD NAME: FromRectl(rectlSrc, eInclusive)
//
// DESCRIPTION:
//
// This method will convert the passed PM RECTL into the area object
//
// NOTE: This guy is NOT exported
// ---------------------------------------
// INPUT: rectlSrc is the source rectangle to convert
// eInclusive indicates whether the rectangle is an inclusive one
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::FromRectl( const RECTL& rectlSrc
, tCIDGui::eRECTLTYPE eInclusive)
{
if (rectlSrc.xLeft > rectlSrc.xRight)
{
__i4X = rectlSrc.xRight;
__c4CX = (rectlSrc.xLeft-rectlSrc.xRight);
}
else
{
__i4X = rectlSrc.xLeft;
__c4CX = (rectlSrc.xRight-rectlSrc.xLeft);
}
if (rectlSrc.yBottom > rectlSrc.yTop)
{
__i4Y = rectlSrc.yTop;
__c4CY = (rectlSrc.yBottom-rectlSrc.yTop);
}
else
{
__i4Y = rectlSrc.yBottom;
__c4CY = (rectlSrc.yTop-rectlSrc.yBottom);
}
// If inclusive, bump up the sizes by 1 if not empty
if (eInclusive == tCIDGui::eRECTL_INCLUSIVE)
{
if (__c4CX)
__c4CX++;
if (__c4CY)
__c4CY++;
}
}
//
// FUNCTION/METHOD NAME: FromSwp(swpSrc)
//
// DESCRIPTION:
//
// This method will convert the passed PM SWP into the area object.
//
// NOTE: This guy is NOT exported
// ---------------------------------------
// INPUT: swpSrc is the source SWP structure to convert
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::FromSwp(const SWP& swpSrc)
{
__i4X = swpSrc.x;
__i4Y = swpSrc.y;
__c4CX = tCIDLib::CARD4(swpSrc.cx);
__c4CY = tCIDLib::CARD4(swpSrc.cy);
}
//
// FUNCTION/METHOD NAME: i4XRight()
// i4XRight(i4NewXRight)
// i4YTop()
// i4YTop(i4NewYTop)
//
// DESCRIPTION:
//
// These methods will return the right or top most pixel. They have no choice
// but to return the same value for an empty or 1 pixel sized area. There is
// a second version of each that allows it to be set. These are just indirect
// methods for setting the size, which is a great convenience.
// ---------------------------------------
// INPUT: i4NewXRight, i4NewYTop are the new right or top side when setting.
//
// OUTPUT: None
//
// RETURN: The coordinate of the right or top most pixel.
//
tCIDLib:: INT4 PROCEXP AREA::i4XRight() const
{
if (__c4CX)
return (__i4X+__c4CX)-1;
else
return (__i4X);
}
tCIDLib:: INT4 PROCEXP AREA::i4XRight(tCIDLib::INT4 i4NewXRight)
{
// Make sure that it is not less than the origin
if (i4NewXRight < __i4X)
{
facCIDGui.LogErr( __FILE__
, "AREA::i4XRight"
, __LINE__
, GUIERR_COORD_AREA_BEHIND_ORG
, "(Horizontal)"
, tCIDLib::eSEV_PROCESS_FATAL
, tCIDLib::eCLASS_BADPARMS
, INTEGER(i4NewXRight)
, INTEGER(__i4X));
}
__c4CX = (i4NewXRight-__i4X)+1;
return i4NewXRight;
}
tCIDLib::INT4 PROCEXP AREA::i4YTop() const
{
if (__c4CY)
return (__i4Y+__c4CY)-1;
else
return (__i4Y);
}
tCIDLib::INT4 PROCEXP AREA::i4YTop(tCIDLib::INT4 i4NewYTop)
{
// Make sure that it is not less than the origin
if (i4NewYTop < __i4Y)
{
facCIDGui.LogErr( __FILE__
, "AREA::i4YTop"
, __LINE__
, GUIERR_COORD_AREA_BEHIND_ORG
, "(Vertical)"
, tCIDLib::eSEV_PROCESS_FATAL
, tCIDLib::eCLASS_BADPARMS
, INTEGER(i4NewYTop)
, INTEGER(__i4Y));
}
__c4CY = (i4NewYTop-__i4Y)+1;
return i4NewYTop;
}
//
// FUNCTION/METHOD NAME: JustifyIn(areaTarget, eHJustify, eVJustify)
//
// DESCRIPTION:
//
// This method will justify this area within the passed target area, using the
// passed justification flags.
// ---------------------------------------
// INPUT: areaTarget is area to justify to
// eHJustify, eVJustify are the justification flags
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::JustifyIn( const AREA& areaTarget
, tCIDLib::eHJUSTIFY eHJustify
, tCIDLib::eVJUSTIFY eVJustify)
{
//
// Handle the horizontal justification
//
switch(eHJustify)
{
case tCIDLib::eHJUSTIFY_LEFT :
// Set the x origin of this area to that of the target
__i4X = areaTarget.__i4X;
break;
case tCIDLib::eHJUSTIFY_CENTER :
// Set the y to target.center/2 - cx/2
__i4X = areaTarget.__i4X+(areaTarget.__c4CX >> 1);
__i4X -= (__c4CX >> 1);
break;
case tCIDLib::eHJUSTIFY_RIGHT :
// Set the x origin of this area to target.right-cx
__i4X = (areaTarget.__i4X+areaTarget.__c4CX)-__c4CX;
break;
default :
facCIDGui.LogMsg( __FILE__
, "AREA::JustifyIn"
, __LINE__
, "Unknown horizontal justification"
, tCIDLib::eSEV_PROCESS_FATAL);
break;
}
//
// Handle the veritical justification
//
switch(eVJustify)
{
case tCIDLib::eVJUSTIFY_BOTTOM :
// Set the y origin of this area to that of the target
__i4Y = areaTarget.__i4Y;
break;
case tCIDLib::eVJUSTIFY_CENTER :
// Set the y to target.center/2 - cy/2
__i4Y = areaTarget.__i4Y+(areaTarget.__c4CY >> 1);
__i4Y -= (__c4CY >> 1);
break;
case tCIDLib::eVJUSTIFY_TOP :
// Set the y origin of this area to target.top-cy
__i4Y = (areaTarget.__i4Y+areaTarget.__c4CY)-__c4CY;
break;
default :
facCIDGui.LogMsg( __FILE__
, "AREA::JustifyIn"
, __LINE__
, "Unknown vertical justification"
, tCIDLib::eSEV_PROCESS_FATAL);
break;
}
}
//
// FUNCTION/METHOD NAME: ToPtlArray(aptlTarget)
//
// DESCRIPTION:
//
// This method will convert the passed area to an array of POINT structures
// that start and end at the lower left corner and go clockwise.
// ---------------------------------------
// INPUT: None
//
// OUTPUT: aptlTarget is a pointer to an array of 5 POINTL structures.
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::ToPtlArray(POINTL* aptlTarget)
{
aptlTarget[0].x = __i4X;
aptlTarget[0].y = __i4Y;
aptlTarget[1].x = __i4X;
if (__c4CY)
{
aptlTarget[1].y = (__i4Y + tCIDLib::INT4(__c4CY)) - 1;
aptlTarget[2].y = (__i4Y + tCIDLib::INT4(__c4CY)) - 1;
}
else
{
aptlTarget[1].y = __i4Y;
aptlTarget[2].y = __i4Y;
}
if (__c4CX)
{
aptlTarget[2].x = (__i4X + tCIDLib::INT4(__c4CX))-1;
aptlTarget[3].x = (__i4X + tCIDLib::INT4(__c4CX))-1;
}
else
{
aptlTarget[2].x = __i4X;
aptlTarget[3].x = __i4X;
}
aptlTarget[3].y = __i4Y;
aptlTarget[4].x = __i4X;
aptlTarget[4].y = __i4Y;
}
//
// FUNCTION/METHOD NAME: ToCornerPtls(ptlLLeft, ptlULeft, ptlURight, ptlLRight)
//
// DESCRIPTION:
//
// This method will fill in the passed POINTL objects with the corners of the
// area.
// ---------------------------------------
// INPUT: None
//
// OUTPUT: ptlLLeft, ptlULeft, ptlURight, ptlLRight are the POINTL structures
// to fill in.
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::ToCornerPtls( POINTL& ptlLLeft
, POINTL& ptlULeft
, POINTL& ptlURight
, POINTL& ptlLRight) const
{
ptlLLeft.x = __i4X;
ptlLLeft.y = __i4Y;
ptlULeft.x = __i4X;
if (__c4CY)
{
ptlULeft.y = (__i4Y + tCIDLib::INT4(__c4CY))-1;
ptlURight.y = (__i4Y + tCIDLib::INT4(__c4CY))-1;
}
else
{
ptlULeft.y = __i4Y;
ptlURight.y = __i4Y;
}
if (__c4CX)
{
ptlURight.x = (__i4X + tCIDLib::INT4(__c4CX))-1;
ptlLRight.x = (__i4X + tCIDLib::INT4(__c4CX))-1;
}
else
{
ptlURight.x = __i4X;
ptlLRight.x = __i4X;
}
ptlLRight.y = __i4Y;
}
//
// FUNCTION/METHOD NAME: ToCornerPnts(pntLLeft, pntULeft, pntURight, pntLRight)
//
// DESCRIPTION:
//
// This method will convert the area to 4 POINT objects that represent the
// corners of the box.
// ---------------------------------------
// INPUT: None
//
// OUTPUT: pntLLeft, pntULeft, pntURight, pntLRight are the POINT objects to
// fill in.
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::ToCornerPnts( POINT& pntLLeft
, POINT& pntULeft
, POINT& pntURight
, POINT& pntLRight) const
{
pntLLeft.i4X(__i4X);
pntLLeft.i4Y(__i4Y);
pntULeft.i4X(__i4X);
if (__c4CY)
{
pntULeft.i4Y((__i4Y+__c4CY)-1);
pntURight.i4Y((__i4Y+__c4CY)-1);
}
else
{
pntULeft.i4Y(__i4Y);
pntURight.i4Y(__i4Y);
}
if (__c4CX)
{
pntURight.i4X((__i4X+__c4CX)-1);
pntLRight.i4X((__i4X+__c4CX)-1);
}
else
{
pntURight.i4X(__i4X);
pntLRight.i4X(__i4X);
}
pntLRight.i4Y(__i4Y);
}
//
// FUNCTION/METHOD NAME: ToPtls(ptlLLeft, ptlURight)
//
// DESCRIPTION:
//
// This method will convert this area to a set of PM POINTL structures.
// ---------------------------------------
// INPUT: None
//
// OUTPUT: ptlLLeft, ptlURight are the two points that will be filled in
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::ToPtls(POINTL& ptlLLeft, POINTL& ptlURight) const
{
ptlLLeft.x = __i4X;
ptlLLeft.y = __i4Y;
if (__c4CX)
ptlURight.x = (__i4X + tCIDLib::INT4(__c4CX))-1;
else
ptlURight.x = __i4X;
if (__c4CY)
ptlURight.y = (__i4Y + tCIDLib::INT4(__c4CY))-1;
else
ptlURight.y = __i4Y;
}
//
// FUNCTION/METHOD NAME: ToRectl(rectlDest, eInclusive)
//
// DESCRIPTION:
//
// This guy will convert the area to a rectangle, which is either inclusive or
// non-inclusive
//
// NOTE: This guy is NOT exported
// ---------------------------------------
// INPUT: eInclusive indicates whether the destination rectangle should be
// an inclusive one or not.
//
// OUTPUT: rectlDest is the destination rectangle to convert to.
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::ToRectl(RECTL& rectlDest
, tCIDGui::eRECTLTYPE eInclusive) const
{
// Create a inclusive rectangle
rectlDest.xLeft = __i4X;
rectlDest.yBottom = __i4Y;
rectlDest.xRight = __i4X+tCIDLib::INT4(__c4CX);
rectlDest.yTop = __i4Y+tCIDLib::INT4(__c4CY);
//
// If the rectangle is inclusive, then bump down the upper right corner
// so that it lies on the upper right sides.
//
if (eInclusive == tCIDGui::eRECTL_INCLUSIVE)
{
if (__c4CX)
rectlDest.xRight--;
if (__c4CY)
rectlDest.yTop--;
}
}
//
// FUNCTION/METHOD NAME: ToSwp(swpDest)
//
// DESCRIPTION:
//
// This method will convert this area object to the destination SWP structure.
//
// NOTE: This guy is NOT exported
// ---------------------------------------
// INPUT: None
//
// OUTPUT: swpDest is the destination SWP structure to convert to
//
// RETURN: None
//
tCIDLib::VOID PROCEXP AREA::ToSwp(SWP& swpSrc) const
{
swpSrc.x = __i4X;
swpSrc.y = __i4Y;
swpSrc.cx = tCIDLib::INT4(__c4CX);
swpSrc.cy = tCIDLib::INT4(__c4CY);
}
// -----------------------------------------------------------------------------
// AREA: Protected, inherited methods
// -----------------------------------------------------------------------------
//
// FUNCTION/METHOD NAME: _bIsEqual(objTarget) const
//
// DESCRIPTION:
//
// ---------------------------------------
// INPUT: objTarget is the target object to compare against
//
// OUTPUT: None
//
// RETURN: eTRUE if the objects are equal, else eFALSE.
//
tCIDLib::eBOOL PROCEXP AREA::_bIsEqual(const CIDOBJECT& objTarget) const
{
// Call our parent version first
if (!CIDSTORABLE::_bIsEqual(objTarget))
return tCIDLib::eFALSE;
// Look at the object as a window
AREA* pareaTarget = (AREA*)(&objTarget);
if (pareaTarget->__i4X != __i4X) return tCIDLib::eFALSE;
if (pareaTarget->__i4Y != __i4Y) return tCIDLib::eFALSE;
if (pareaTarget->__c4CX != __c4CX) return tCIDLib::eFALSE;
if (pareaTarget->__c4CY != __c4CY) return tCIDLib::eFALSE;
return tCIDLib::eTRUE;
}
// -----------------------------------------------------------------------------
// CLASS: POINT
// PREFIX: pnt
//
// This class defines a 2 dimensional point.
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// POINT: Constructors and Destructors
// -----------------------------------------------------------------------------
//
// FUNCTION/METHOD NAME: POINT(pntSrc)
// POINT()
// POINT(x, y)
// POINT(ptlSrc)
//
// DESCRIPTION:
//
// These are the various constructors for the POINT class.
// ---------------------------------------
// INPUT: pntSrc is the source POINT for the copy constructor
// i4X, i4Y are the x,y values to construct from separate x,y values.
// ptlSrc is the PM POINTL struct to construct from.
//
// OUTPUT: None
//
// RETURN: None
//
PROCEXP POINT::POINT(const POINT& pntSrc) :
__i4X(pntSrc.__i4X)
, __i4Y(pntSrc.__i4Y)
{
}
PROCEXP POINT::POINT() :
__i4X(0)
, __i4Y(0)
{
}
PROCEXP POINT::POINT(const POINTL& ptlSrc) :
__i4X(ptlSrc.x)
, __i4Y(ptlSrc.y)
{
}
PROCEXP POINT::POINT(tCIDLib::INT4 i4X, tCIDLib::INT4 i4Y) :
__i4X(i4X)
, __i4Y(i4Y)
{
}
// -----------------------------------------------------------------------------
// POINT: Public, inherited methods
// -----------------------------------------------------------------------------
//
// FUNCTION/METHOD NAME: FormatAt(pszBuf, c4CurInd);
//
// DESCRIPTION:
//
// This message is called to format this class' members into the passed buffer.
// ---------------------------------------
// INPUT: pszBuf is a pointer to the buffer to format into
// c4CurInd is the index at which this class should start formatting.
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP
POINT::FormatAt(tCIDLib::CH* pszBuf, tCIDLib::CARD4& c4CurInd) const
{
// Call our parent's version
CIDSTORABLE::FormatAt(pszBuf, c4CurInd);
// Address our starting position in the buffer and remember where we started
tCIDLib::CH* pszTmp = &pszBuf[c4CurInd];
tCIDLib::CH* pszStart = pszTmp;
// Write out the origin and size information
*(tCIDLib::INT4*)pszTmp = __i4X;
pszTmp += sizeof(__i4X);
*(tCIDLib::INT4*)pszTmp = __i4Y;
pszTmp += sizeof(__i4Y);
// Bump up cCurInd by the bytes we used
c4CurInd += tCIDLib::CARD4(pszTmp-pszStart);
}
//
// FUNCTION/METHOD NAME: FormatToStr(strbDest) const
//
// DESCRIPTION:
//
// This method will format the data members into the passed string buffer
// ---------------------------------------
// INPUT: None
//
// OUTPUT: strbDest is the buffer to format into
//
// RETURN: None
//
tCIDLib::VOID PROCEXP POINT::FormatToStr(STRGBUF& strbDest) const
{
strbDest << "X=" << __i4X << ",Y=" << __i4Y;
}
//
// FUNCTION/METHOD NAME: ParseAt(pszBuf, c4CurInd)
//
// DESCRIPTION:
//
// This method will parse the data from the passed buffer into this object. We
// first call our parent class, then parse out our data members.
// ---------------------------------------
// INPUT: pszBuf is the buffer to parse from.
// c4CurInd is where we start parsing from.
//
// OUTPUT: c4CurInd is bumped up by the number of bytes parsed at this level
// and all below us
//
// RETURN: None
//
tCIDLib::VOID PROCEXP
POINT::ParseAt(const tCIDLib::CH* pszBuf, tCIDLib::CARD4& c4CurInd)
{
// Call our parent's version
CIDSTORABLE::ParseAt(pszBuf, c4CurInd);
// Address our starting position in the buffer
const tCIDLib::CH* pszTmp = &pszBuf[c4CurInd];
const tCIDLib::CH* pszStart = pszTmp;
// Get the vector value
__i4X = *(tCIDLib::CARD4*)pszTmp;
pszTmp += sizeof(__i4X);
__i4Y = *(tCIDLib::CARD4*)pszTmp;
pszTmp += sizeof(__i4Y);
// Bump up cCurInd by the bytes we used
c4CurInd += tCIDLib::CARD4(pszTmp-pszStart);
}
// -----------------------------------------------------------------------------
// POINT: Public, non-virtual methods
// -----------------------------------------------------------------------------
//
// FUNCTION/METHOD NAME: operator POINT*() const
//
// DESCRIPTION:
//
// This guy allows us to pass point objects straight to POINTL pointers
// internally.
// ---------------------------------------
// INPUT: None
//
// OUTPUT: None
//
// RETURN: A pointer to the __i4X element, cast to a POINTL*
//
PROCEXP POINT::operator POINTL*() const
{
return (POINTL*)&__i4X;
}
//
// FUNCTION/METHOD NAME: bInArea(areaTarget) const
//
// DESCRIPTION:
//
// This method checks to see if the point is in the passed area.
// ---------------------------------------
// INPUT: areaTarget is the area to check against
//
// OUTPUT: None
//
// RETURN: eTRUE if the point is in the passed area, else eFALSE.
//
tCIDLib::eBOOL PROCEXP POINT::bInArea(const AREA& areaTarget) const
{
if ((__i4X < areaTarget.i4X())
|| (__i4Y < areaTarget.i4Y())
|| (__i4X > areaTarget.i4XRight())
|| (__i4Y > areaTarget.i4YTop()))
{
return tCIDLib::eFALSE;
}
return tCIDLib::eTRUE;
}
//
// FUNCTION/METHOD NAME: FromPtl(ptlSrc)
//
// DESCRIPTION:
//
// This method will parse the passed PM POINTL into this object
// ---------------------------------------
// INPUT: ptlSrc is the source PM POINT to parse
//
// OUTPUT: None
//
// RETURN: None
//
tCIDLib::VOID PROCEXP POINT::FromPtl(const POINTL& ptlSrc)
{
__i4X = ptlSrc.x;
__i4Y = ptlSrc.y;
}
//
// FUNCTION/METHOD NAME: ToPtl(ptlTarget)
//
// DESCRIPTION:
//
// This method will fill the passed PM POINTL with this object's point info
// ---------------------------------------
// INPUT: None
//
// OUTPUT: ptlTarget is the target of the point information
//
// RETURN: None
//
tCIDLib::VOID PROCEXP POINT::ToPtl(POINTL& ptlTarget) const
{
ptlTarget.x = __i4X;
ptlTarget.y = __i4Y;
}
// -----------------------------------------------------------------------------
// POINT: Protected, inherited methods
// -----------------------------------------------------------------------------
//
// FUNCTION/METHOD NAME: _bIsEqual(objTarget) const
//
// DESCRIPTION:
//
// This method will compare this object's members at this class level with
// those of the target object.
// ---------------------------------------
// INPUT: objTarget is the target object to compare against
//
// OUTPUT: None
//
// RETURN: eTRUE if the objects are equal, else eFALSE.
//
tCIDLib::eBOOL PROCEXP POINT::_bIsEqual(const CIDOBJECT& objTarget) const
{
// Call our parent's version first
if (!CIDSTORABLE::_bIsEqual(objTarget))
return tCIDLib::eFALSE;
// Look at the object as a window
POINT* ppntTarget = (POINT*)(&objTarget);
if (ppntTarget->__i4X != __i4X) return tCIDLib::eFALSE;
if (ppntTarget->__i4Y != __i4Y) return tCIDLib::eFALSE;
return tCIDLib::eTRUE;
}