/* $Header$ */

// base WP object class implementation

/**************** Changes ******************
Date			Edit				Bug					Description
31-Dec-18	rmm9881			ST/EC/1524	Issues with RTF on reports - text spanning pages had problems, and tabs did not always render nicely.
12-Apr-16	rmm8853									Help window appearance issues.
01-Jun-15	rmmhdpi									High DPI support for Windows.
22 MAY 00	mpm4700									Implements printing of document
08 NOV 99 mlr0006									Added Rtf support
********************************************/

#ifndef _extcomp_
#include "extcomp.he" // jmg_includecasing
#endif

#ifndef	_WPOBJECT_HE_
#include "wpobject.he" // jmg_includecasing
#endif



// ###############################################################################
// ################# qlrect Public ###############################################
// ###############################################################################


qbool	qlrect::unionRect( qlrect* pRect1, qlrect* pRect2 )
{
	left =  ( pRect1->left < pRect2->left ? pRect1->left : pRect2->left );
	top =  ( pRect1->top < pRect2->top ? pRect1->top : pRect2->top );
	right =  ( pRect1->right > pRect2->right ? pRect1->right : pRect2->right );
	bottom =  ( pRect1->bottom > pRect2->bottom ? pRect1->bottom : pRect2->bottom );
	
	return (qbool)( top <= bottom && left <= right );
}


qbool qlrect::intersectRect( qlrect* pRect1, qlrect* pRect2 )
{
	left =  ( pRect1->left > pRect2->left ? pRect1->left : pRect2->left );
	top =  ( pRect1->top > pRect2->top ? pRect1->top : pRect2->top );
	right =  ( pRect1->right < pRect2->right ? pRect1->right : pRect2->right );
	bottom =  ( pRect1->bottom < pRect2->bottom ? pRect1->bottom : pRect2->bottom );
	
	return (qbool)( top <= bottom && left <= right );
}


void qlrect::norm()
{
	if ( top > bottom ) { qldim tmp = top; top = bottom; bottom = tmp; }
	if ( left > right ) { qldim tmp = left; left = right; right = tmp; }
}


void qlrect::normVertPt()
{
	if ( top > bottom )
	{
		qldim tmp = top; top = bottom; bottom = tmp;
		tmp = left; left = right; right = tmp;
	}
}


qbool qlrect::isEmpty()
{
	return width() == 0 && height() == 0;
}


qbool qlrect::conv( qrect* pDestRect )
{
	pDestRect->top = top;
	pDestRect->left = left;
	pDestRect->bottom = bottom;
	pDestRect->right = right;
	return ( ( left & 0x7FFF0000 ) + ( top & 0x7FFF0000 ) + ( right & 0x7FFF0000 ) + ( bottom & 0x7FFF0000 ) ) == 0;
}


qbool	qlrect::ptInRect( qpoint* pPoint )
{
	if ( pPoint->h >= left && pPoint->h <= right && pPoint->v >= top && pPoint->v <= bottom )
		return qtrue;
	else
		return qfalse;
}


static qpridim sPRIconvFrom( qlong pUnits, qpridim pDeviceUnits ) // mpm4700 begins
{
	if ( pUnits < 0 )
		return qpridim( ( qpridim(pUnits) * PRI_INCH - pDeviceUnits/2 ) / pDeviceUnits );
	else
		return qpridim( ( qpridim(pUnits) * PRI_INCH + pDeviceUnits/2 ) / pDeviceUnits );
}


static qlong sPRIconvTo( qpridim pUnits, qdim pDeviceUnits )
{
	if ( pUnits < 0 )
		return qpridim( ( qreal(pUnits) * qreal(pDeviceUnits) - PRI_1_2INCH ) / PRI_INCH ); // mpm4600
	else
		return qpridim( ( qreal(pUnits) * qreal(pDeviceUnits) + PRI_1_2INCH ) / PRI_INCH ); // mpm4600
}

void qlrect::convto( qprirect* pPriRect )
{
	qdim	horz, vert; GDIgetScreenResolution( &horz, &vert );
	horz = GDIconvToDesign(horz, qfalse);	// rmmhdpi
	vert = GDIconvToDesign(vert, qtrue);	// rmmhdpi
	pPriRect->left = 1 + sPRIconvFrom( left, horz ); 
	pPriRect->right = 1 + sPRIconvFrom( right, horz ); 
	pPriRect->top = 1 + sPRIconvFrom( top, vert ); 
	pPriRect->bottom = 1 + sPRIconvFrom( bottom, vert ); 
}

void qlrect::convfrom( qprirect* pPriRect )
{
	qdim	horz, vert; GDIgetScreenResolution( &horz, &vert );
	horz = GDIconvToDesign(horz, qfalse);	// rmmhdpi
	vert = GDIconvToDesign(vert, qtrue);	// rmmhdpi
	left = sPRIconvTo(pPriRect->left, horz);
	right = sPRIconvTo( pPriRect->right, horz );
	top = sPRIconvTo( pPriRect->top, vert );
	bottom = sPRIconvTo( pPriRect->bottom, vert );
} // mpm4700 ends

// rmm9881:
qldim qlrect::convfrom(qpridim pValue, qbool pVert)
{
	qdim	horz, vert; GDIgetScreenResolution(&horz, &vert);
	horz = GDIconvToDesign(horz, qfalse);
	vert = GDIconvToDesign(vert, qtrue);
	return pVert ? sPRIconvTo(pValue, vert) : sPRIconvTo(pValue, horz);
}

// ###############################################################################
// ################# WPObjectClass Public ########################################
// ###############################################################################


WPObjectClass::WPObjectClass( WPObjectClass* pParent, WPDocClass* pDocumentObj )
{
	mParent = mFirstChild = mLastChild = mPrevSibling = mNextSibling = 0;
	mDocumentObj = pDocumentObj;
	if ( pParent ) insert( this, pParent, 0 );
}


WPObjectClass::~WPObjectClass()
{
	WPObjectClass* child = mFirstChild;
	while ( child )
	{
		WPObjectClass* nextChild = child->mNextSibling;
		delete child;
		child = nextChild;
	}
}


void WPObjectClass::insert( WPObjectClass* pObject, WPObjectClass* pParent, WPObjectClass* pBefore )
{
	pObject->mParent = pParent;
	if ( pBefore )
	{
		pObject->mNextSibling = pBefore;
		pObject->mPrevSibling = pBefore->mPrevSibling;
		if ( pBefore->mPrevSibling )
			pBefore->mPrevSibling->mNextSibling = pObject;
		else
			pParent->mFirstChild = pObject;
		pBefore->mPrevSibling = pObject;
	}
	else
	{
		if ( pParent->mLastChild )
		{
			pParent->mLastChild->mNextSibling = pObject;
			pObject->mPrevSibling = pParent->mLastChild;
			pParent->mLastChild = pObject;
		}
		else
		{
			pParent->mFirstChild = pParent->mLastChild = pObject;
		}
	}
}


void WPObjectClass::remove( WPObjectClass* pObject )
{
	if ( pObject->mPrevSibling )
		pObject->mPrevSibling->mNextSibling = pObject->mNextSibling;
	else if ( pObject->mParent )
		pObject->mParent->mFirstChild = pObject->mNextSibling;
		
	if ( pObject->mNextSibling )
		pObject->mNextSibling->mPrevSibling = pObject->mPrevSibling;
	else if ( pObject->mParent )
		pObject->mParent->mLastChild = pObject->mPrevSibling;
		
	pObject->mPrevSibling = pObject->mNextSibling = pObject->mParent = 0;
	
}


void WPObjectClass::initData( WPObjInfoStruct* pObjInfo,printInfo* pInfo )
{
	WPObjectClass* child = mFirstChild;
	while ( child )
	{
		pObjInfo->mOwner = child;
		pObjInfo->mOwnerData1 = pObjInfo->mOwnerData2 = 0;
		pObjInfo->mOwnerRect.top = pObjInfo->mOwnerRect.bottom = pObjInfo->mRowRect.top;
		pObjInfo->mOwnerRect.left = pObjInfo->mOwnerRect.right + 1;
		pObjInfo->mOwnerBaseLine = 0; // means no base line
		child->initData( pObjInfo, pInfo);
		child = child->mNextSibling;
	}
}


void WPObjectClass::addRowInfo( WPObjInfoStruct* pObjInfo )
{
}


void WPObjectClass::addParaInfo( WPObjInfoStruct* pObjInfo )
{
}


void WPObjectClass::newRow( WPObjInfoStruct* pObjInfo )
{
	pObjInfo->mNumber++;
	pObjInfo->mOwnerBaseLine = 0;
	qlrect& childOwnerRect = pObjInfo->mOwnerRect;
	qlrect& childRowRect = pObjInfo->mRowRect;
	childOwnerRect.top = childOwnerRect.bottom = childOwnerRect.bottom + 1;
	childOwnerRect.left = childOwnerRect.right = childRowRect.left; childOwnerRect.right--;
	childRowRect.top = childRowRect.bottom = childOwnerRect.top;
}


void WPObjectClass::newPara( WPObjInfoStruct* pObjInfo )
{
	newRow( pObjInfo );
}


void WPObjectClass::paint( WPObjInfoStruct* pObjInfo, WNDpaintStruct* pPaintStruct, qldim pHorzOff, qldim pVertOff )
{
	WPObjectClass* child = mFirstChild;
	while ( child )
	{
		child->paint( pObjInfo, pPaintStruct, pHorzOff, pVertOff );
		child = child->mNextSibling;
	}
}


qldim WPObjectClass::getMinWidth() // mpm4700
{
	qldim minwid = 4;
	WPObjectClass* child = mFirstChild;
	while ( child )
	{
		qldim minwid1 = child->getMinWidth();
		if ( minwid1 > minwid ) minwid = minwid1;
		child = child->mNextSibling;
	}
	return minwid;
}


qprierr WPObjectClass::addToPrintJob( printInfo* pInfo, EXTCompInfo* eci, WPObjInfoStruct* pObjInfo, // mpm4700
																			qldim& pHorzOff, qldim& pVertOff)
{
	qprierr err = PRI_ERR_NONE;
	WPObjectClass* child = mFirstChild;
	while ( child )
	{
		err = child->addToPrintJob(pInfo,eci,pObjInfo,pHorzOff,pVertOff);
		if ( err >= PRI_ERR_MANAGER_CLOSED ) break; // only break on fatal errors
		child = child->mNextSibling;
	}
	return err;
}


qlong WPObjectClass::message( WPObjInfoStruct* pObjInfo, eWPMessage pMessage, qldim pHorzOff, qldim pVertOff, LPARAM lParam1, LPARAM lParam2 )
{
	qlong result = 0;
	WPObjectClass* child = mFirstChild;
	while ( child )
	{
		if ((result = child->message( pObjInfo, pMessage, pHorzOff, pVertOff, lParam1, lParam2 )) != 0) return result;
		child = child->mNextSibling;
	}
	return result;
}


HCURSOR WPObjectClass::getCursor( WPObjInfoStruct* pObjInfo, qpoint* pPoint )
{
	return WND_CURS_DEFAULT;
}


WPLinkInfoStruct* WPObjectClass::getLinkInfo()
{
	return 0;
}


void WPObjectClass::setLinkInfo( WPLinkInfoStruct* pLinkInfo )
{
}


void WPObjectClass::setSpaceBefore( qshort pSpace )
{
}


void WPObjectClass::setSpaceAfter( qshort pSpace )
{
}


qcol WPObjectClass::getBackColor()
{
	if ( mParent )
		return mParent->getBackColor();
	else
		return GDI_COLOR_WINDOW; // rmm8853
}

void WPObjectClass::orphanSetNext(WPObjectClass * secText)
{
	WPObjectClass * tempNextSibling = this ;
	while  ( tempNextSibling->mNextSibling !=NULL )
	{
		tempNextSibling=tempNextSibling->mNextSibling;
	}
	tempNextSibling->mNextSibling = secText ;
	secText->mPrevSibling = this ;

}  // end of orphanSetNext


// ###############################################################################
// ################# Global functions ############################################
// ###############################################################################


static qlong screenUnits = 0;

qdim WPpointsToDims( qshort pPoints )
{
	if ( !screenUnits )
	{
		qdim horz,vert; GDIgetScreenResolution( &horz, &vert );
		horz = GDIconvToDesign(horz, qfalse);	// rmmhdpi
		screenUnits = horz;
	}
	return qdim( qlong(pPoints) * screenUnits / 72 );
}

/* eof */


