/**************************************************************
 * 
 * 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 <txtftn.hxx>
#include <fmtftn.hxx>
#include <ftninfo.hxx>
#include <doc.hxx>
#include <ftnidx.hxx>
#include <ndtxt.hxx>
#include <ndindex.hxx>
#include <section.hxx>
#include <fmtftntx.hxx>
#include <rootfrm.hxx>


_SV_IMPL_SORTAR_ALG( _SwFtnIdxs, SwTxtFtnPtr )
sal_Bool _SwFtnIdxs::Seek_Entry( const SwTxtFtnPtr rSrch, sal_uInt16* pFndPos ) const
{
	sal_uLong nIdx = _SwTxtFtn_GetIndex( rSrch );
	xub_StrLen nCntIdx = *rSrch->GetStart();

	sal_uInt16 nO = Count(), nM, nU = 0;
	if( nO > 0 )
	{
		nO--;
		while( nU <= nO )
		{
			nM = nU + ( nO - nU ) / 2;
			sal_uLong nFndIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
			if( nFndIdx == nIdx && *(*this)[ nM ]->GetStart() == nCntIdx )
			{
				if( pFndPos )
					*pFndPos = nM;
				return sal_True;
			}
			else if( nFndIdx < nIdx ||
				(nFndIdx == nIdx && *(*this)[ nM ]->GetStart() < nCntIdx ))
				nU = nM + 1;
			else if( nM == 0 )
			{
				if( pFndPos )
					*pFndPos = nU;
				return sal_False;
			}
			else
				nO = nM - 1;
		}
	}
	if( pFndPos )
		*pFndPos = nU;
	return sal_False;
}


void SwFtnIdxs::UpdateFtn( const SwNodeIndex& rStt )
{
	if( !Count() )
		return;

	// besorge erstmal das Nodes-Array ueber den StartIndex der ersten Fussnote
	SwDoc* pDoc = rStt.GetNode().GetDoc();
	if( pDoc->IsInReading() )
		return ;
	SwTxtFtn* pTxtFtn;

	const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
	const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();

	//Fuer normale Fussnoten werden Chapter- und Dokumentweise Nummerierung
	//getrennt behandelt. Fuer Endnoten gibt es nur die Dokumentweise
	//Nummerierung.
	if( FTNNUM_CHAPTER == rFtnInfo.eNum )
	{
		const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
		const SwNode* pCapStt = &pDoc->GetNodes().GetEndOfExtras();
		sal_uLong nCapEnd = pDoc->GetNodes().GetEndOfContent().GetIndex();
		if( rOutlNds.Count() )
		{
			// suche den Start des Kapitels, in den rStt steht.
			sal_uInt16 n;

			for( n = 0; n < rOutlNds.Count(); ++n )
				if( rOutlNds[ n ]->GetIndex() > rStt.GetIndex() )
					break;		// gefunden
				//else if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() )	//#outline level,zhaojianwei
                else if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )   //<-end,zhaojianwei
					pCapStt = rOutlNds[ n ];	// Start eines neuen Kapitels
			// dann suche jetzt noch das Ende vom Bereich
			for( ; n < rOutlNds.Count(); ++n )
				//if( !rOutlNds[ n ]->GetTxtNode()->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
                if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
				{
					nCapEnd = rOutlNds[ n ]->GetIndex();	// Ende des gefundenen Kapitels
					break;
				}
		}

		sal_uInt16 nPos, nFtnNo = 1;
		if( SeekEntry( *pCapStt, &nPos ) && nPos )
		{
			// gehe nach vorne bis der Index nicht mehr gleich ist
			const SwNode* pCmpNd = &rStt.GetNode();
			while( nPos && pCmpNd == &((*this)[ --nPos ]->GetTxtNode()) )
				;
			++nPos;
		}

		if( nPos == Count() )		// nichts gefunden
			return;

		if( !rOutlNds.Count() )
			nFtnNo = nPos+1;

		for( ; nPos < Count(); ++nPos )
		{
			pTxtFtn = (*this)[ nPos ];
			if( pTxtFtn->GetTxtNode().GetIndex() >= nCapEnd )
				break;

			const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
			if( !rFtn.GetNumStr().Len() && !rFtn.IsEndNote() &&
				!SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
				pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nFtnNo++,
									&rFtn.GetNumStr() );
		}
	}

	SwUpdFtnEndNtAtEnd aNumArr;

	// sal_Bool, damit hier auch bei Chapter-Einstellung die Endnoten
	// durchlaufen.
	const sal_Bool bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;

	sal_uInt16 nPos, nFtnNo = 1, nEndNo = 1;
	sal_uLong nUpdNdIdx = rStt.GetIndex();
	for( nPos = 0; nPos < Count(); ++nPos )
	{
		pTxtFtn = (*this)[ nPos ];
		if( nUpdNdIdx <= pTxtFtn->GetTxtNode().GetIndex() )
			break;

		const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
		if( !rFtn.GetNumStr().Len() )
		{
			if( !aNumArr.ChkNumber( *pTxtFtn ) )
			{
				if( pTxtFtn->GetFtn().IsEndNote() )
					nEndNo++;
				else
					nFtnNo++;
			}
		}
	}

	// ab nPos bei allen FootNotes die Array-Nummer setzen
	for( ; nPos < Count(); ++nPos )
	{
		pTxtFtn = (*this)[ nPos ];
		const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
		if( !rFtn.GetNumStr().Len() )
		{
			sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTxtFtn );
			if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
				nSectNo = rFtn.IsEndNote()
							? rEndInfo.nFtnOffset + nEndNo++
							: rFtnInfo.nFtnOffset + nFtnNo++;

			if( nSectNo )
			{
				if( rFtn.IsEndNote() )
					pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
				else
					pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
			}
		}
	}
	// Pageweise wird vom MA erfuellt !!
}


void SwFtnIdxs::UpdateAllFtn()
{
	if( !Count() )
		return;

	// besorge erstmal das Nodes-Array ueber den StartIndex der
	// ersten Fussnote
	SwDoc* pDoc = (SwDoc*) (*this)[ 0 ]->GetTxtNode().GetDoc();
	SwTxtFtn* pTxtFtn;
	const SwEndNoteInfo& rEndInfo = pDoc->GetEndNoteInfo();
	const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();

	SwUpdFtnEndNtAtEnd aNumArr;

	SwRootFrm* pTmpRoot = pDoc->GetCurrentLayout();//swmod 080305
	std::set<SwRootFrm*> aAllLayouts = pDoc->GetAllLayouts();
	//Fuer normale Fussnoten werden Chapter- und Dokumentweise Nummerierung
	//getrennt behandelt. Fuer Endnoten gibt es nur die Dokumentweise
	//Nummerierung.
	if( FTNNUM_CHAPTER == rFtnInfo.eNum )
	{
		const SwOutlineNodes& rOutlNds = pDoc->GetNodes().GetOutLineNds();
		sal_uInt16 nNo = 1,			// Nummer fuer die Fussnoten
			   nFtnIdx = 0;		// Index in das FtnIdx-Array
		for( sal_uInt16 n = 0; n < rOutlNds.Count(); ++n )
		{
            if ( rOutlNds[ n ]->GetTxtNode()->GetAttrOutlineLevel() == 1 )//<-end,zhaojianwei
			{
				sal_uLong nCapStt = rOutlNds[ n ]->GetIndex();	// Start eines neuen Kapitels
				for( ; nFtnIdx < Count(); ++nFtnIdx )
				{
					pTxtFtn = (*this)[ nFtnIdx ];
					if( pTxtFtn->GetTxtNode().GetIndex() >= nCapStt )
						break;

					// Endnoten nur Dokumentweise
					const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
					if( !rFtn.IsEndNote() && !rFtn.GetNumStr().Len() &&
						!SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
						pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++,
											&rFtn.GetNumStr() );
				}
				if( nFtnIdx >= Count() )
					break;			// ok alles geupdatet
				nNo = 1;
			}
		}

		for( nNo = 1; nFtnIdx < Count(); ++nFtnIdx )
		{
			//Endnoten nur Dokumentweise
			pTxtFtn = (*this)[ nFtnIdx ];
			const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
			if( !rFtn.IsEndNote() && !rFtn.GetNumStr().Len() &&
				!SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtFtn ))
				pTxtFtn->SetNumber( rFtnInfo.nFtnOffset + nNo++,
									&rFtn.GetNumStr() );
		}

	}

	// sal_Bool, damit hier auch bei Chapter-Einstellung die Endnoten
	// durchlaufen.
	const sal_Bool bEndNoteOnly = FTNNUM_DOC != rFtnInfo.eNum;
	sal_uInt16 nFtnNo = 0, nEndNo = 0;
	for( sal_uInt16 nPos = 0; nPos < Count(); ++nPos )
	{
		pTxtFtn = (*this)[ nPos ];
		const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
		if( !rFtn.GetNumStr().Len() )
		{
			sal_uInt16 nSectNo = aNumArr.ChkNumber( *pTxtFtn );
			if( !nSectNo && ( rFtn.IsEndNote() || !bEndNoteOnly ))
				nSectNo = rFtn.IsEndNote()
								? rEndInfo.nFtnOffset + (++nEndNo)
								: rFtnInfo.nFtnOffset + (++nFtnNo);

			if( nSectNo )
			{
				if( rFtn.IsEndNote() )
					pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
				else
					pTxtFtn->SetNumber( nSectNo, &rFtn.GetNumStr() );
			}
		}
	}

	if( pTmpRoot && FTNNUM_PAGE == rFtnInfo.eNum )
		std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFtnNums));//swmod 0
}

SwTxtFtn* SwFtnIdxs::SeekEntry( const SwNodeIndex& rPos, sal_uInt16* pFndPos ) const
{
	sal_uLong nIdx = rPos.GetIndex();

	sal_uInt16 nO = Count(), nM, nU = 0;
	if( nO > 0 )
	{
		nO--;
		while( nU <= nO )
		{
			nM = nU + ( nO - nU ) / 2;
			sal_uLong nNdIdx = _SwTxtFtn_GetIndex( (*this)[ nM ] );
			if( nNdIdx == nIdx )
			{
				if( pFndPos )
					*pFndPos = nM;
				return (*this)[ nM ];
			}
			else if( nNdIdx < nIdx )
				nU = nM + 1;
			else if( nM == 0 )
			{
				if( pFndPos )
					*pFndPos = nU;
				return 0;
			}
			else
				nO = nM - 1;
		}
	}
	if( pFndPos )
		*pFndPos = nU;
	return 0;
}

/*  */

const SwSectionNode* SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr(
				const SwTxtFtn& rTxtFtn )
{
	sal_uInt16 nWh = static_cast<sal_uInt16>( rTxtFtn.GetFtn().IsEndNote() ?
                        RES_END_AT_TXTEND :	RES_FTN_AT_TXTEND );
	sal_uInt16 nVal;
	const SwSectionNode* pNd = rTxtFtn.GetTxtNode().FindSectionNode();
	while( pNd && FTNEND_ATTXTEND_OWNNUMSEQ != ( nVal =
			((const SwFmtFtnAtTxtEnd&)pNd->GetSection().GetFmt()->
            GetFmtAttr( nWh, sal_True )).GetValue() ) &&
			FTNEND_ATTXTEND_OWNNUMANDFMT != nVal )
        pNd = pNd->StartOfSectionNode()->FindSectionNode();

	return pNd;
}

sal_uInt16 SwUpdFtnEndNtAtEnd::GetNumber( const SwTxtFtn& rTxtFtn,
									const SwSectionNode& rNd )
{
	sal_uInt16 nRet = 0, nWh;
	SvPtrarr* pArr;
	SvUShorts* pNum;
	if( rTxtFtn.GetFtn().IsEndNote() )
	{
		pArr = &aEndSects;
		pNum = &aEndNums;
		nWh = RES_END_AT_TXTEND;
	}
	else
	{
		pArr = &aFtnSects;
		pNum = &aFtnNums;
		nWh = RES_FTN_AT_TXTEND;
	}
	void* pNd = (void*)&rNd;

	for( sal_uInt16 n = pArr->Count(); n; )
		if( pArr->GetObject( --n ) == pNd )
		{
			nRet = ++pNum->GetObject( n );
			break;
		}

	if( !nRet )
	{
		pArr->Insert( pNd, pArr->Count() );
		nRet = ((SwFmtFtnEndAtTxtEnd&)rNd.GetSection().GetFmt()->
                                GetFmtAttr( nWh )).GetOffset();
		++nRet;
		pNum->Insert( nRet, pNum->Count() );
	}
	return nRet;
}

sal_uInt16 SwUpdFtnEndNtAtEnd::ChkNumber( const SwTxtFtn& rTxtFtn )
{
	const SwSectionNode* pSectNd = FindSectNdWithEndAttr( rTxtFtn );
	return pSectNd ? GetNumber( rTxtFtn, *pSectNd ) : 0;
}




