/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include <switerator.hxx>
#include <calbck.hxx>	
#include <node.hxx>
#include <ndindex.hxx>
#include <swtable.hxx>
#include <ftnfrm.hxx>
#include <sectfrm.hxx>
#include "frmfmt.hxx"
#include "cntfrm.hxx"
#include "tabfrm.hxx"
#include "frmtool.hxx"
#include "section.hxx"
#include "node2lay.hxx"

/* -----------------25.02.99 10:31-------------------
 * Die SwNode2LayImpl-Klasse erledigt die eigentliche Arbeit,
 * die SwNode2Layout-Klasse ist nur die der Oefffentlichkeit bekannte Schnittstelle
 * --------------------------------------------------*/
class SwNode2LayImpl
{
	SwIterator<SwFrm,SwModify>* pIter;
    SwModify* pMod;
	SvPtrarr *pUpperFrms;// Zum Einsammeln der Upper
	sal_uLong nIndex;        // Der Index des einzufuegenden Nodes
	sal_Bool bMaster	: 1; // sal_True => nur Master , sal_False => nur Frames ohne Follow
	sal_Bool bInit		: 1; // Ist am SwClient bereits ein First()-Aufruf erfolgt?
public:
	SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, sal_Bool bSearch );
	~SwNode2LayImpl() { delete pIter; delete pUpperFrms; }
	SwFrm* NextFrm(); // liefert den naechsten "sinnvollen" Frame
	SwLayoutFrm* UpperFrm( SwFrm* &rpFrm, const SwNode &rNode );
	void SaveUpperFrms(); // Speichert (und lockt ggf.) die pUpper
	// Fuegt unter jeden pUpper des Arrays einen Frame ein.
	void RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd );

	SwFrm* GetFrm( const Point* pDocPos = 0,
					const SwPosition *pPos = 0,
					const sal_Bool bCalcFrm = sal_True ) const;
};

/* -----------------25.02.99 10:38-------------------
 * Hauptaufgabe des Ctor: Das richtige SwModify zu ermitteln,
 * ueber das iteriert wird.
 * Uebergibt man bSearch == sal_True, so wird der naechste Cntnt- oder TableNode
 * gesucht, der Frames besitzt ( zum Einsammeln der pUpper ), ansonsten wird
 * erwartet, das rNode bereits auf einem solchen Cntnt- oder TableNode sitzt,
 * vor oder hinter den eingefuegt werden soll.
 * --------------------------------------------------*/

SwNode* GoNextWithFrm(const SwNodes& rNodes, SwNodeIndex *pIdx)
{
	if( pIdx->GetIndex() >= rNodes.Count() - 1 )
		return 0;

	SwNodeIndex aTmp(*pIdx, +1);
    SwNode* pNd = 0;
	while( aTmp < rNodes.Count()-1 )
	{
		pNd = &aTmp.GetNode();
        bool bFound = false;
		if ( pNd->IsCntntNode() )
			bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0);
		else if ( pNd->IsTableNode() )
			bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 );
        else if( pNd->IsEndNode() && !pNd->StartOfSectionNode()->IsSectionNode() )
		{
			pNd = 0;
			break;
		}
		if ( bFound )
				break;
		aTmp++;
	}

	if( aTmp == rNodes.Count()-1 )
		pNd = 0;
	else if( pNd )
		(*pIdx) = aTmp;
	return pNd;
}

SwNode* GoPreviousWithFrm(SwNodeIndex *pIdx)
{
	if( !pIdx->GetIndex() )
		return 0;

	SwNodeIndex aTmp( *pIdx, -1 );
	SwNode* pNd(0);
	while( aTmp.GetIndex() )
	{
		pNd = &aTmp.GetNode();
        bool bFound = false;
		if ( pNd->IsCntntNode() )
			bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0);
		else if ( pNd->IsTableNode() )
			bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 );
		else if( pNd->IsStartNode() && !pNd->IsSectionNode() )
		{
			pNd = 0;
			break;
		}
		if ( bFound )
				break;
		aTmp--;
	}

	if( !aTmp.GetIndex() )
		pNd = 0;
	else if( pNd )
		(*pIdx) = aTmp;
	return pNd;
}


SwNode2LayImpl::SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, sal_Bool bSearch )
	: pUpperFrms( NULL ), nIndex( nIdx ), bInit( sal_False )
{
	const SwNode* pNd;
	if( bSearch || rNode.IsSectionNode() )
	{
		// Suche den naechsten Cntnt/TblNode, der einen Frame besitzt,
		// damit wir uns vor/hinter ihn haengen koennen
		if( !bSearch && rNode.GetIndex() < nIndex )
		{
			SwNodeIndex aTmp( *rNode.EndOfSectionNode(), +1 );
			pNd = GoPreviousWithFrm( &aTmp );
			if( !bSearch && pNd && rNode.GetIndex() > pNd->GetIndex() )
				pNd = NULL; // Nicht ueber den Bereich hinausschiessen
			bMaster = sal_False;
		}
		else
		{
			SwNodeIndex aTmp( rNode, -1 );
			pNd = GoNextWithFrm( rNode.GetNodes(), &aTmp );
			bMaster = sal_True;
			if( !bSearch && pNd && rNode.EndOfSectionIndex() < pNd->GetIndex() )
				pNd = NULL; // Nicht ueber den Bereich hinausschiessen
		}
	}
	else
	{
		pNd = &rNode;
		bMaster = nIndex < rNode.GetIndex();
	}
	if( pNd )
	{
		if( pNd->IsCntntNode() )
			pMod = (SwModify*)pNd->GetCntntNode();
		else
		{
			ASSERT( pNd->IsTableNode(), "For Tablenodes only" );
			pMod = pNd->GetTableNode()->GetTable().GetFrmFmt();
		}
		pIter = new SwIterator<SwFrm,SwModify>( *pMod );
	}
	else
    {
		pIter = NULL;
        pMod = 0;
    }
}

/* -----------------25.02.99 10:41-------------------
 * SwNode2LayImpl::NextFrm() liefert den naechsten "sinnvollen" Frame,
 * beim ersten Aufruf wird am eigentlichen Iterator ein First gerufen,
 * danach die Next-Methode. Das Ergebnis wird auf Brauchbarkeit untersucht,
 * so werden keine Follows akzeptiert, ein Master wird beim Einsammeln der
 * pUpper und beim Einfuegen vor ihm akzeptiert. Beim Einfuegen dahinter
 * wird vom Master ausgehend der letzte Follow gesucht und zurueckgegeben.
 * Wenn der Frame innerhalb eines SectionFrms liegt, wird noch festgestellt,
 * ob statt des Frames der SectionFrm der geeignete Rueckgabewert ist, dies
 * ist der Fall, wenn der neu einzufuegende Node ausserhalb des Bereichs liegt.
 * --------------------------------------------------*/
SwFrm* SwNode2LayImpl::NextFrm()
{
	SwFrm* pRet;
	if( !pIter )
		return NULL;
	if( !bInit )
	{
		 pRet = pIter->First();
		 bInit = sal_True;
	}
	else
		pRet = pIter->Next();
	while( pRet )
	{
		SwFlowFrm* pFlow = SwFlowFrm::CastFlowFrm( pRet );
		ASSERT( pFlow, "Cntnt or Table expected?!" );
		// Follows sind fluechtige Gestalten, deshalb werden sie ignoriert.
		// Auch wenn wir hinter dem Frame eingefuegt werden sollen, nehmen wir
		// zunaechst den Master, hangeln uns dann aber zum letzten Follow durch.
		if( !pFlow->IsFollow() )
		{
			if( !bMaster )
			{
				while( pFlow->HasFollow() )
					pFlow = pFlow->GetFollow();
				pRet = pFlow->GetFrm();
			}
			if( pRet->IsInSct() )
			{
				SwSectionFrm* pSct = pRet->FindSctFrm();
				// Vorsicht: Wenn wir in einer Fussnote sind, so kann diese
				// Layoutmaessig in einem spaltigen Bereich liegen, obwohl
				// sie nodemaessig ausserhalb liegt. Deshalb muss bei Fussnoten
				// ueberprueft werden, ob auch der SectionFrm in der Fussnote
				// und nicht ausserhalb liegt.
				if( !pRet->IsInFtn() || pSct->IsInFtn() )
				{
					ASSERT( pSct && pSct->GetSection(), "Where's my section?" );
					SwSectionNode* pNd = pSct->GetSection()->GetFmt()->GetSectionNode();
					ASSERT( pNd, "Lost SectionNode" );
					// Wenn der erhaltene Frame in einem Bereichsframe steht,
					// dessen Bereich den Ausgangsnode nicht umfasst, so kehren
					// wir mit dem SectionFrm zurueck, sonst mit dem Cntnt/TabFrm
					if( bMaster )
					{
						if( pNd->GetIndex() >= nIndex )
							pRet = pSct;
					}
					else if( pNd->EndOfSectionIndex() < nIndex )
						pRet = pSct;
				}
			}
			return pRet;
		}
		pRet = pIter->Next();
	}
	return NULL;
}

void SwNode2LayImpl::SaveUpperFrms()
{
	pUpperFrms = new SvPtrarr( 0, 20 );
	SwFrm* pFrm;
	while( 0 != (pFrm = NextFrm()) )
	{
		SwFrm* pPrv = pFrm->GetPrev();
		pFrm = pFrm->GetUpper();
		if( pFrm )
		{
			if( pFrm->IsFtnFrm() )
				((SwFtnFrm*)pFrm)->ColLock();
			else if( pFrm->IsInSct() )
				pFrm->FindSctFrm()->ColLock();
			if( pPrv && pPrv->IsSctFrm() )
				((SwSectionFrm*)pPrv)->LockJoin();
			pUpperFrms->Insert( (void*)pPrv, pUpperFrms->Count() );
			pUpperFrms->Insert( (void*)pFrm, pUpperFrms->Count() );
		}
	}
	delete pIter;
	pIter = NULL;
    pMod = 0;
}

SwLayoutFrm* SwNode2LayImpl::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode )
{
	rpFrm = NextFrm();
	if( !rpFrm )
		return NULL;
	SwLayoutFrm* pUpper = rpFrm->GetUpper();
	if( rpFrm->IsSctFrm() )
	{
		const SwNode* pNode = rNode.StartOfSectionNode();
		if( pNode->IsSectionNode() )
		{
			SwFrm* pFrm = bMaster ? rpFrm->FindPrev() : rpFrm->FindNext();
			if( pFrm && pFrm->IsSctFrm() )
			{
                // #137684#: pFrm could be a "dummy"-section
				if( ((SwSectionFrm*)pFrm)->GetSection() &&
                    (&((SwSectionNode*)pNode)->GetSection() ==
                     ((SwSectionFrm*)pFrm)->GetSection()) )
				{
                    // OD 2004-06-02 #i22922# - consider columned sections
                    // 'Go down' the section frame as long as the layout frame
                    // is found, which would contain content.
                    while ( pFrm->IsLayoutFrm() &&
                            static_cast<SwLayoutFrm*>(pFrm)->Lower() &&
                            !static_cast<SwLayoutFrm*>(pFrm)->Lower()->IsFlowFrm() &&
                            static_cast<SwLayoutFrm*>(pFrm)->Lower()->IsLayoutFrm() )
                    {
                        pFrm = static_cast<SwLayoutFrm*>(pFrm)->Lower();
                    }
                    ASSERT( pFrm->IsLayoutFrm(),
                            "<SwNode2LayImpl::UpperFrm(..)> - expected upper frame isn't a layout frame." );
                    rpFrm = bMaster ? NULL
                                    : static_cast<SwLayoutFrm*>(pFrm)->Lower();
                    ASSERT( !rpFrm || rpFrm->IsFlowFrm(),
                            "<SwNode2LayImpl::UpperFrm(..)> - expected sibling isn't a flow frame." );
                    return static_cast<SwLayoutFrm*>(pFrm);
				}

                pUpper = new SwSectionFrm(((SwSectionNode*)pNode)->GetSection(), rpFrm);
				pUpper->Paste( rpFrm->GetUpper(),
							   bMaster ? rpFrm : rpFrm->GetNext() );
                static_cast<SwSectionFrm*>(pUpper)->Init();
				rpFrm = NULL;
                // 'Go down' the section frame as long as the layout frame
                // is found, which would contain content.
                while ( pUpper->Lower() &&
                        !pUpper->Lower()->IsFlowFrm() &&
                        pUpper->Lower()->IsLayoutFrm() )
                {
                    pUpper = static_cast<SwLayoutFrm*>(pUpper->Lower());
                }
				return pUpper;
			}
		}
	};
	if( !bMaster )
		rpFrm = rpFrm->GetNext();
	return pUpper;
}

void SwNode2LayImpl::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd )
{
	ASSERT( pUpperFrms, "RestoreUpper without SaveUpper?" )
	SwNode* pNd;
	SwDoc *pDoc = rNds.GetDoc();
	sal_Bool bFirst = sal_True;
	for( ; nStt < nEnd; ++nStt )
	{
		SwFrm* pNew = 0;
		SwFrm* pNxt;
		SwLayoutFrm* pUp;
		if( (pNd = rNds[nStt])->IsCntntNode() )
			for( sal_uInt16 n = 0; n < pUpperFrms->Count(); )
			{
				pNxt = (SwFrm*)(*pUpperFrms)[n++];
				if( bFirst && pNxt && pNxt->IsSctFrm() )
					((SwSectionFrm*)pNxt)->UnlockJoin();
				pUp = (SwLayoutFrm*)(*pUpperFrms)[n++];
				if( pNxt )
					pNxt = pNxt->GetNext();
				else
					pNxt = pUp->Lower();
				pNew = ((SwCntntNode*)pNd)->MakeFrm( pUp );
				pNew->Paste( pUp, pNxt );
				(*pUpperFrms)[n-2] = pNew;
			}
		else if( pNd->IsTableNode() )
			for( sal_uInt16 x = 0; x < pUpperFrms->Count(); )
			{
				pNxt = (SwFrm*)(*pUpperFrms)[x++];
				if( bFirst && pNxt && pNxt->IsSctFrm() )
					((SwSectionFrm*)pNxt)->UnlockJoin();
				pUp = (SwLayoutFrm*)(*pUpperFrms)[x++];
				if( pNxt )
					pNxt = pNxt->GetNext();
				else
					pNxt = pUp->Lower();
				pNew = ((SwTableNode*)pNd)->MakeFrm( pUp );
				ASSERT( pNew->IsTabFrm(), "Table exspected" );
				pNew->Paste( pUp, pNxt );
				((SwTabFrm*)pNew)->RegistFlys();
				(*pUpperFrms)[x-2] = pNew;
			}
		else if( pNd->IsSectionNode() )
		{
			nStt = pNd->EndOfSectionIndex();
			for( sal_uInt16 x = 0; x < pUpperFrms->Count(); )
			{
				pNxt = (SwFrm*)(*pUpperFrms)[x++];
				if( bFirst && pNxt && pNxt->IsSctFrm() )
					((SwSectionFrm*)pNxt)->UnlockJoin();
				pUp = (SwLayoutFrm*)(*pUpperFrms)[x++];
				ASSERT( pUp->GetUpper() || pUp->IsFlyFrm(), "Lost Upper" );
				::_InsertCnt( pUp, pDoc, pNd->GetIndex(), sal_False, nStt+1, pNxt );
                pNxt = pUp->GetLastLower();
                (*pUpperFrms)[x-2] = pNxt;
			}
		}
		bFirst = sal_False;
	}
	for( sal_uInt16 x = 0; x < pUpperFrms->Count(); ++x )
	{
		SwFrm* pTmp = (SwFrm*)(*pUpperFrms)[++x];
		if( pTmp->IsFtnFrm() )
			((SwFtnFrm*)pTmp)->ColUnlock();
        else if ( pTmp->IsInSct() )
        {
            SwSectionFrm* pSctFrm = pTmp->FindSctFrm();
            pSctFrm->ColUnlock();
            // OD 26.08.2003 #i18103# - invalidate size of section in order to
            // assure, that the section is formatted, unless it was 'Collocked'
            // from its 'collection' until its 'restoration'.
            pSctFrm->_InvalidateSize();
        }
	}
}

SwFrm* SwNode2LayImpl::GetFrm( const Point* pDocPos,
								const SwPosition *pPos,
								const sal_Bool bCalcFrm ) const
{
    // mba: test if change of member pIter -> pMod broke anything
	return pMod ? ::GetFrmOfModify( 0, *pMod, USHRT_MAX, pDocPos, pPos, bCalcFrm ) : 0;
}

SwNode2Layout::SwNode2Layout( const SwNode& rNd, sal_uLong nIdx )
{
	pImpl = new SwNode2LayImpl( rNd, nIdx, sal_False );
}

SwNode2Layout::SwNode2Layout( const SwNode& rNd )
{
	pImpl = new SwNode2LayImpl( rNd, rNd.GetIndex(), sal_True );
	pImpl->SaveUpperFrms();
}

void SwNode2Layout::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd )
{
	ASSERT( pImpl, "RestoreUpperFrms without SaveUpperFrms" );
	pImpl->RestoreUpperFrms( rNds, nStt, nEnd );
}

SwFrm* SwNode2Layout::NextFrm()
{
	return pImpl->NextFrm();
}

SwLayoutFrm* SwNode2Layout::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode )
{
	return pImpl->UpperFrm( rpFrm, rNode );
}

SwNode2Layout::~SwNode2Layout()
{
	delete pImpl;
}

SwFrm* SwNode2Layout::GetFrm( const Point* pDocPos,
								const SwPosition *pPos,
								const sal_Bool bCalcFrm ) const
{
	return pImpl->GetFrm( pDocPos, pPos, bCalcFrm );
}


