netscape-revival
lib/mac/VText/V_PowerPlant_Mods/URange32.cp
// ===========================================================================
// URange32.cp ©1994 Metrowerks Inc. All rights reserved.
// ===========================================================================
#ifdef PowerPlant_PCH
#include PowerPlant_PCH
#endif
#include "URange32.h"
#pragma warn_unusedarg off
const Range32T Range32T::sAll(0, max_Int32);
const Range32T Range32T::sUndefined;
#ifndef Profile_Range32T
#pragma push
#pragma profile off
#endif
// ----------------------------------------------------------------------
void Range32T::SetLength(Int32 inLength)
{
if (inLength < 0) {
Throw_(paramErr);
} else if (inLength == 0) {
length = rangeCode_Before;
// Assert_(false); // sure you wouldn't rather use the unambiguous SetLength(length, insertion)?
} else {
length = inLength;
}
}
Range32T::Range32T(
Int32 inStart,
Int32 inLength,
ERangeCode inInsertion) // iff inLength == 0
{
if (inLength) {
start = inStart;
length = inLength;
} else {
start = inStart;
SetInsertion(inInsertion);
}
}
void Range32T::SetLength(
Int32 inLength,
ERangeCode inInsertion) // iff inLength == 0
{
if (inLength < 0) {
Throw_(paramErr);
} else if (inLength == 0) {
SetInsertion(inInsertion);
} else {
length = inLength;
}
}
void Range32T::MoveStart(Int32 inStart)
{
Int32 end = End();
start = inStart;
SetEnd(end);
}
void Range32T::SetInsertion(ERangeCode inCode)
{
Assert_(inCode != 0);
Assert_(inCode & 0x80000000);
length = inCode;
}
void Range32T::SetRange(
Int32 inOneInsertion,
Int32 inAnotherInsertion,
ERangeCode inCode)
{
if (inOneInsertion < inAnotherInsertion) {
start = inOneInsertion;
SetEnd(inAnotherInsertion);
} else if (inOneInsertion > inAnotherInsertion) {
start = inAnotherInsertion;
SetEnd(inOneInsertion);
} else {
start = inOneInsertion;
SetInsertion(inCode);
}
}
// ======================================================================
Range32T& Range32T::Before(void)
{
SetInsertion(rangeCode_Before);
return *this;
}
Range32T& Range32T::Front(void)
{
if (Length())
SetInsertion(rangeCode_After);
return *this;
}
Range32T& Range32T::Back(void)
{
if (Length()) {
SetStart(End());
SetInsertion(rangeCode_Before);
}
return *this;
}
Range32T& Range32T::After(void)
{
start = start + Length();
SetInsertion(rangeCode_After);
return *this;
}
Range32T& Range32T::Crop(const Range32T &inRange)
// Crop "this" to inrange
{
if (!inRange.Contains(*this)) {
if (inRange.Length()) {
if (End() <= inRange.Start()) {
start = inRange.Start();
SetInsertion(rangeCode_After);
} else if (Start() >= inRange.End()) {
start = inRange.End();
SetInsertion(rangeCode_Before);
} else {
Int32 newStart = URange32::Max(Start(), inRange.Start()),
newEnd = URange32::Min(End(), inRange.End());
start = newStart;
SetEnd(newEnd);
Assert_(Length());
}
} else {
*this = inRange;
}
Assert_(inRange.Contains(*this));
}
return *this;
}
Range32T& Range32T::WeakCrop(const Range32T &inRange)
{
if (!inRange.WeakContains(*this))
Crop(inRange);
return *this;
}
Range32T& Range32T::Union(const Range32T &inRange)
/*
Union isn't closed...
Consider rangeCode_Before | rangeCode_After
Will default to rangeCode_Before
*/
{
if (this != &inRange) {
if (Undefined()) {
*this = inRange;
} else if (!inRange.Undefined()) {
Int32 min = URange32::Min( Start(), inRange.Start() ),
max = URange32::Max( End(), inRange.End() );
start = min;
SetLength(max - min);
}
}
return *this;
}
Range32T& Range32T::Intersection(const Range32T &inRange)
{
Int32 thisLength = Length(),
thatLength = inRange.Length();
if (*this == inRange) {
// don't change
} else if ((thisLength == 0) && (thatLength == 0)) {
SetInsertion(rangeCode_Undefined);
} else if (thatLength == 0) {
Range32T range = inRange;
range.Intersection(*this);
*this = range;
} else if (thisLength == 0) {
if ((Start() == inRange.Start()) && (Insertion() == rangeCode_Before)) {
SetInsertion(rangeCode_Undefined);
} else if ((Start() == inRange.End()) && (Insertion() == rangeCode_After)) {
SetInsertion(rangeCode_Undefined);
} else if ((inRange.Start() <= Start()) && (Start() <= inRange.End())) {
// nada;
} else {
SetInsertion(rangeCode_Undefined);
}
} else {
Int32 min = URange32::Max(Start(), inRange.Start()),
max = URange32::Min(End(), inRange.End());
if (min <= max) {
start = min;
SetLength(max - min);
} else {
length = rangeCode_Undefined;
}
}
return *this;
}
Range32T& Range32T::Insert(const Range32T &inRangePt, Int32 inAmount)
/*
Find the range when inAmount is inserted at inRangePt.
inRangePt.Length() must == 0.
inAmount must >= 0.
*/
{
if (inRangePt.Length() != 0)
Throw_(paramErr);
if (inAmount < 0)
Throw_(paramErr);
if (inAmount) {
if (Contains(inRangePt)) {
SetLength(Length() + inAmount);
} else {
if (inRangePt.Start() <= Start()) {
start += inAmount;
} else {
Assert_(inRangePt.Start() >= End());
}
}
}
return *this;
}
Range32T& Range32T::Delete(const Range32T &inRange)
/*
Return the range when inRange is deleted.
*/
{
if (inRange.Length()) {
if (Length()) {
if (Contains(inRange)) {
SetLength(Length() - inRange.Length());
} else if (Intersects(inRange)) {
if (Start() < inRange.Start()) {
SetEnd(inRange.Start());
} else {
Int32 len = End() - inRange.End();
if (len < 0)
len = 0;
start = inRange.Start();
SetLength(len);
}
} else if (Start() >= inRange.End()) {
start -= inRange.Length();
}
} else {
if (Start() <= inRange.Start()) {
// nada;
} else {
start -= URange32::Min(Start() - inRange.Start(), inRange.Length());
}
}
}
return *this;
}
Range32T& Range32T::Adjust(
const Range32T &inRange,
Int32 inLengthDelta,
Boolean inInclusive)
{
if (inRange.Length() + inLengthDelta < 0)
Throw_(paramErr); // Illegal parameters.
if (!inRange.Length()) {
// a simple insert
Insert(inRange, inLengthDelta);
} else if (inRange.Length() == -inLengthDelta) {
// a simple delete
Delete(inRange);
} else if (Contains(inRange)) {
// range resize
SetLength(Length() + inLengthDelta);
} else if (End() <= inRange.Start()) {
// before change
// nada
} else if (Start() >= inRange.End()) {
// after change
Translate(inLengthDelta);
} else if ((Start() < inRange.Start()) && (End() < inRange.End())) {
// left intersects
if (inInclusive) {
SetEnd(inRange.End() + inLengthDelta);
} else {
SetEnd(inRange.Start());
}
} else if ((Start() > inRange.Start()) && (End() > inRange.End())) {
// right intersects
Int32 end = End() + inLengthDelta;
if (inInclusive) {
SetStart(inRange.Start());
} else {
SetStart(inRange.End() + inLengthDelta);
}
SetEnd(end);
} else if (inRange.Contains(*this)) {
if (inInclusive) {
SetStart(inRange.Start());
SetLength(inRange.Length() + inLengthDelta);
} else {
*this = inRange;
Front();
}
} else {
// What else is there?
Throw_(paramErr);
}
return *this;
}
// ======================================================================
Boolean Range32T::Adjacent(const Range32T &inRange) const
/*
Does this share only a boundary position with inRange?
*/
{
Boolean rval = false;
if (*this == inRange) {
rval = Length() == 0;
} else {
Range32T range = inRange;
range.Intersection(*this);
if (range.Length()) {
rval = false;
} else if (End() == inRange.Start()) {
rval = true;
} else if (Start() == inRange.End()) {
rval = true;
}
}
return rval;
}
Boolean Range32T::Contains(const Range32T &inRange) const
/*
Does this range contain inRange.
*/
{
Boolean rval = false;
if (*this == inRange) {
rval = true;
} else if (Length()) {
if (inRange.Length()) {
if ((Start() <= inRange.Start()) && (inRange.End() <= End()))
rval = true;
} else {
if ((Start() < inRange.Start()) && (inRange.Start() < End())) {
rval = true;
} else if ((Start() == inRange.Start()) && (inRange.Insertion() == rangeCode_After)) {
rval = true;
} else if ((End() == inRange.End()) && (inRange.Insertion() == rangeCode_Before)) {
rval = true;
}
}
}
return rval;
}
Boolean Range32T::WeakContains(const Range32T &inRange) const
{
return (Start() <= inRange.Start()) && (inRange.End() <= End());
}
Boolean Range32T::Intersects(const Range32T &inRange) const
/*
Does this intersect with the range on the right hand side
*/
{
Range32T temp = *this;
temp.Intersection(inRange);
return !temp.Undefined();
}
Boolean Range32T::IsBefore(const Range32T &inRange) const
/*
Is this entirely before inRange
*/
{
if (End() < inRange.Start())
return true;
if (End() > inRange.Start())
return false;
if (inRange.Insertion() == rangeCode_Before) {
return false;
} else {
return Insertion() != rangeCode_After;
}
}
Boolean Range32T::IsAfter(const Range32T &inRange) const
{
return inRange.IsBefore(*this);
}
Range32T& Range32T::Translate(Int32 inAmount)
{
start += inAmount;
return *this;
}
EScanDirection Range32T::GetScanDirection(
const Range32T &inKnownBounds,
const Range32T &inPoint) const
{
Assert_(!Undefined());
Assert_(!inKnownBounds.Undefined());
Assert_(!inPoint.Undefined());
Assert_(!inPoint.Length());
EScanDirection direction;
Range32T range;
if (inKnownBounds.Contains(inPoint)) {
// in known bounds (most likely in caching situations so test occurs first?)
if ((inKnownBounds.End() - inPoint.Start()) < (inPoint.Start() - inKnownBounds.Start()))
direction = scanDirection_rn;
else
direction = scanDirection_lp;
} else if (Contains(inPoint)) {
if (inPoint.IsBefore(inKnownBounds)) {
// left of known bounds
if ((inKnownBounds.Start() - inPoint.Start()) < (inPoint.Start() - Start()))
direction = scanDirection_ln;
else
direction = scanDirection_bp;
} else {
Assert_(inPoint.IsAfter(inKnownBounds));
// right of known bounds
if ((End() - inPoint.Start()) < (inPoint.Start() - inKnownBounds.End()))
direction = scanDirection_en;
else
direction = scanDirection_rp;
}
} else {
// outside "this"
if (inPoint.Start() <= inKnownBounds.Start())
direction = scanDirection_bn;
else
direction = scanDirection_ep;
}
return direction;
}
StRange32TChanger::StRange32TChanger(
Range32T &ioVariable,
Range32T inNewValue)
: mVariable(ioVariable),
mOrigValue(ioVariable)
{
ioVariable = inNewValue;
}
StRange32TChanger::~StRange32TChanger()
{
Range32T temp(mVariable);
mVariable = mOrigValue;
}
#ifndef Profile_Range32T
#pragma pop
#endif
// ===========================================================================
// Static members:
const Domain32T Domain32T::sAll(Range32T::sAll, Range32T::sAll);
const Domain32T Domain32T::sUndefined(Range32T::sUndefined, Range32T::sUndefined);
// ===========================================================================
// Domain32T:
Domain32T::Domain32T()
{
*this = Domain32T::sUndefined;
}
Domain32T::Domain32T(const Range32T &inWidth, const Range32T &inHeight)
{
width = inWidth;
height = inHeight;
}
void Domain32T::SetWidth(const Range32T &inRange)
{
width = inRange;
}
void Domain32T::SetHeight(const Range32T &inRange)
{
height = inRange;
}
const Range32T & Domain32T::Width(void) const
{
return width;
}
const Range32T & Domain32T::Height(void) const
{
return height;
}
Boolean Domain32T::IsInsertion(void) const
{
return (height.Length() == 0) || (width.Length() == 0);
}
Boolean Domain32T::operator==(const Domain32T &inRange) const
{
if ((width == inRange.width) && (height == inRange.height))
return true;
else
return false;
}
Boolean Domain32T::Undefined(void) const
{
return width.Undefined() || height.Undefined();
}
Boolean Domain32T::Intersects(const Domain32T &inRange) const
{
Domain32T temp = *this;
temp.Intersection(inRange);
return !temp.Undefined();
}
Domain32T& Domain32T::Intersection(const Domain32T &inRange)
{
width.Intersection(inRange.Width());
height.Intersection(inRange.Height());
return *this;
}
Boolean Domain32T::Adjacent(const Domain32T &inRange) const
{
Boolean rval = false;
rval = width.Adjacent(inRange.Width()) && height.Adjacent(inRange.Height());
return rval;
}
Domain32T& Domain32T::Crop(const Domain32T &inRange)
{
width.Crop(inRange.Width());
height.Crop(inRange.Height());
return *this;
}
Boolean Domain32T::Contains(const Domain32T &inRange) const
{
Boolean h = width.Contains(inRange.Width()),
v = height.Contains(inRange.Height());
return h && v;
}
Domain32T& Domain32T::Translate(Int32 inHorz, Int32 inVert)
{
width.Translate(inHorz);
height.Translate(inVert);
return *this;
}
Domain32T& Domain32T::Insert(const Domain32T &inRangePt, Int32 inAmount)
/*
Can only insert on a width and or height when the width or height is an "Insertion"
*/
{
if (!inRangePt.Width().Length())
width.Insert(inRangePt.Width(), inAmount);
if (!inRangePt.Height().Length())
height.Insert(inRangePt.Height(), inAmount);
return *this;
}
Domain32T& Domain32T::Delete(const Domain32T &inRange)
{
if (inRange.Width().Length())
width.Delete(inRange.Width());
if (inRange.Height().Length())
height.Delete(inRange.Height());
return *this;
}
Domain32T& Domain32T::Union(const Domain32T &inRange)
{
width.Union(inRange.Width());
height.Union(inRange.Height());
return *this;
}
void Domain32T::ToRect(Rect &outRect) const
/*
ASSUMED that *this will not overflow the smaller outRect
*/
{
outRect.top = Height().Start();
outRect.left = Width().Start();
outRect.right = outRect.left + Width().Length();
outRect.bottom = outRect.top + Height().Length();
}
void Domain32T::SetRect(const Rect &inRect)
{
SetHeight(Range32T(inRect.top, inRect.bottom));
SetWidth(Range32T(inRect.left, inRect.right));
}
// ===========================================================================
// URange32
//
// Utility functions for dealing with Range32T variables.
Int32 URange32::Min(Int32 inA, Int32 inB)
{
if (inA < inB)
return inA;
else
return inB;
}
Int32 URange32::Max(Int32 inA, Int32 inB)
{
if (inA > inB)
return inA;
else
return inB;
}
Int32 URange32::Abs(Int32 inA)
{
if (inA > 0)
return inA;
else
return -inA;
}
#ifdef PP_USEOLDRANGE32
Boolean URange32::RangesSame(const Range32T &inRangeA, const Range32T &inRangeB)
{
return inRangeA == inRangeB;
}
Boolean URange32::RangeWithinRange(const Range32T &inRangeA, const Range32T &inRangeB)
{
return (inRangeA.Start() >= inRangeB.Start()) &&
(inRangeA.End() <= inRangeB.End());
}
Boolean URange32::RangeIntersection(
const Range32T &inRangeA,
const Range32T &inRangeB,
Range32T *outRange)
{
Int32 aStart = inRangeA.start,
bStart = inRangeB.start,
aEnd = inRangeA.start + inRangeA.length,
bEnd = inRangeB.start + inRangeB.length;
if ( (aStart < bStart ) && (aEnd < bStart) )
return false;
if ( (bStart < aStart ) && (bEnd < aStart) )
return false;
if (outRange) {
outRange->start = Max(aStart, bStart);
outRange->length = Min(aEnd, bEnd) - outRange->start;
}
return true;
}
Boolean URange32::RangeUnion(
const Range32T &inRangeA,
const Range32T &inRangeB,
Range32T *outRange)
{
Int32 start, end;
start = Min(inRangeA.start, inRangeB.start);
end = Max(inRangeA.start + inRangeA.length, inRangeB.start + inRangeB.length);
if (outRange) {
outRange->start = start;
outRange->length = end - start;
}
return true;
}
void URange32::RangeShift(const Range32T &inRange, Int32 inDelta, Range32T *outRange)
{
Assert_(outRange);
outRange->start = inRange.start + inDelta;
outRange->length = inRange.length;
}
void URange32::RangeExpand(const Range32T &inRange, Int32 inDelta, Range32T *outRange)
{
Assert_(outRange);
outRange->start = inRange.start;
outRange->length = inRange.length + inDelta;
}
void URange32::RangeCrop(
const Range32T &inRange,
const Range32T &inBoundary,
Range32T *outRange)
{
Int32 start = inRange.Start(),
end = inRange.End(),
bStart = inBoundary.Start(),
bEnd = inBoundary.End();
start = Max(start, bStart);
end = Min(end, bEnd);
start = Min(start, bEnd);
end = Max(end, bStart);
outRange->start = start;
outRange->length = end - start;
Assert_(outRange->length >= 0);
}
void URange32::RangeAdjust(
const Range32T &inRange,
Int32 inStart,
Int32 inDelta,
Boolean inInclusive,
Range32T *outRange)
/*
if
inDelta > 0
|inDelta| units are added at inStart.
inDelta < 0
|inDelta| units are being removed beginning at inStart and proceeding
"to the right," "next," "sequentially."
Note: Inclusive parameter doesn't apply when inDelta < 0.
*/
{
Range32T range = inRange;
Int32 range_end = range.End(),
headDelta = 0,
lengthDelta = 0;
if (inDelta > 0) {
if (inInclusive) {
if ( (range.start <= inStart) && (inStart <= range_end) ) {
lengthDelta = inDelta;
}
if (inStart < range.start) {
headDelta = inDelta;
}
} else {
if ( (range.start < inStart) && (inStart < range_end) ) {
lengthDelta = inDelta;
}
if (inStart <= range.start) {
headDelta = inDelta;
}
}
} else {
if ( (range.start <= inStart) && (inStart < range_end) ) {
lengthDelta = -URange32::Min(range_end - inStart, -inDelta);
Assert_(lengthDelta <= 0);
}
if (inStart < range.start) {
Int32 in_end = inStart + (-inDelta);
if (range.start < in_end) {
lengthDelta = -URange32::Min(in_end - range.start, range.length);
}
headDelta = -URange32::Min(range.start - inStart, -inDelta);
}
}
range.start += headDelta;
range.length += lengthDelta;
Assert_(range.start >= 0);
Assert_(range.length >= 0);
*outRange = range;
}
#endif