/**************************************************************
 * 
 * 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 <UndoRedline.hxx>

#include <hintids.hxx>
#include <unotools/charclass.hxx>
#include <doc.hxx>
#include <swundo.hxx>			// fuer die UndoIds
#include <pam.hxx>
#include <ndtxt.hxx>
#include <UndoCore.hxx>
#include <UndoDelete.hxx>
#include <rolbck.hxx>
#include <redline.hxx>
#include <docary.hxx>
#include <sortopt.hxx>

extern void lcl_JoinText( SwPaM& rPam, sal_Bool bJoinPrev );
extern void lcl_GetJoinFlags( SwPaM& rPam, sal_Bool& rJoinTxt, sal_Bool& rJoinPrev );

//------------------------------------------------------------------

SwUndoRedline::SwUndoRedline( SwUndoId nUsrId, const SwPaM& rRange )
	: SwUndo( UNDO_REDLINE ), SwUndRng( rRange ),
	mpRedlData( 0 ), mpRedlSaveData( 0 ), mnUserId( nUsrId ),
	mbHiddenRedlines( sal_False )
{
	// Redline beachten
	SwDoc& rDoc = *rRange.GetDoc();
	if( rDoc.IsRedlineOn() )
	{
		switch( mnUserId )
		{
		case UNDO_DELETE:
		case UNDO_REPLACE:
			mpRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_DELETE, rDoc.GetRedlineAuthor() );
			break;
        default:
            ;
		}
		SetRedlineMode( rDoc.GetRedlineMode() );
	}

	sal_uLong nEndExtra = rDoc.GetNodes().GetEndOfExtras().GetIndex();

	mpRedlSaveData = new SwRedlineSaveDatas;
	if( !FillSaveData( rRange, *mpRedlSaveData, sal_False,
						UNDO_REJECT_REDLINE != mnUserId ))
		delete mpRedlSaveData, mpRedlSaveData = 0;
	else
	{
		mbHiddenRedlines = HasHiddenRedlines( *mpRedlSaveData );
		if( mbHiddenRedlines ) 			// dann muessen die NodeIndizies
		{   							// vom SwUndRng korrigiert werden
			nEndExtra -= rDoc.GetNodes().GetEndOfExtras().GetIndex();
			nSttNode -= nEndExtra;
			nEndNode -= nEndExtra;
		}
	}
}

SwUndoRedline::~SwUndoRedline()
{
	delete mpRedlData;
	delete mpRedlSaveData;
}

sal_uInt16 SwUndoRedline::GetRedlSaveCount() const
{
    return mpRedlSaveData ? mpRedlSaveData->Count() : 0;
}


void SwUndoRedline::UndoImpl(::sw::UndoRedoContext & rContext)
{
    SwDoc *const pDoc = & rContext.GetDoc();
    SwPaM & rPam( AddUndoRedoPaM(rContext) );

    UndoRedlineImpl(*pDoc, rPam);

	if( mpRedlSaveData )
	{
		sal_uLong nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex();
		SetSaveData( *pDoc, *mpRedlSaveData );
		if( mbHiddenRedlines )
		{
			mpRedlSaveData->DeleteAndDestroy( 0, mpRedlSaveData->Count() );

			nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex() - nEndExtra;
			nSttNode += nEndExtra;
			nEndNode += nEndExtra;
		}
        SetPaM(rPam, true);
    }
}


void SwUndoRedline::RedoImpl(::sw::UndoRedoContext & rContext)
{
    SwDoc *const pDoc = & rContext.GetDoc();
	RedlineMode_t eOld = pDoc->GetRedlineMode();
	pDoc->SetRedlineMode_intern((RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON ));

    SwPaM & rPam( AddUndoRedoPaM(rContext) );
	if( mpRedlSaveData && mbHiddenRedlines )
	{
		sal_uLong nEndExtra = pDoc->GetNodes().GetEndOfExtras().GetIndex();
        FillSaveData(rPam, *mpRedlSaveData, sal_False,
						UNDO_REJECT_REDLINE != mnUserId );

		nEndExtra -= pDoc->GetNodes().GetEndOfExtras().GetIndex();
		nSttNode -= nEndExtra;
		nEndNode -= nEndExtra;
	}

    RedoRedlineImpl(*pDoc, rPam);

    SetPaM(rPam, true);
	pDoc->SetRedlineMode_intern( eOld );
}

void SwUndoRedline::UndoRedlineImpl(SwDoc &, SwPaM &)
{
}

// default: remove redlines
void SwUndoRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
{
    rDoc.DeleteRedline(rPam, true, USHRT_MAX);
}


// SwUndoRedlineDelete ///////////////////////////////////////////////////

SwUndoRedlineDelete::SwUndoRedlineDelete( const SwPaM& rRange, SwUndoId nUsrId )
    : SwUndoRedline( nUsrId = (nUsrId ? nUsrId : UNDO_DELETE), rRange ),
	bCanGroup( sal_False ), bIsDelim( sal_False ), bIsBackspace( sal_False )
{
	const SwTxtNode* pTNd;
	if( UNDO_DELETE == mnUserId &&
		nSttNode == nEndNode && nSttCntnt + 1 == nEndCntnt &&
		0 != (pTNd = rRange.GetNode()->GetTxtNode()) )
	{
		sal_Unicode cCh = pTNd->GetTxt().GetChar( nSttCntnt );
		if( CH_TXTATR_BREAKWORD != cCh && CH_TXTATR_INWORD != cCh )
		{
			bCanGroup = sal_True;
			bIsDelim = !GetAppCharClass().isLetterNumeric( pTNd->GetTxt(),
															nSttCntnt );
			bIsBackspace = nSttCntnt == rRange.GetPoint()->nContent.GetIndex();
		}
	}

    bCacheComment = false;
}

void SwUndoRedlineDelete::UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
{
    rDoc.DeleteRedline(rPam, true, USHRT_MAX);
}

void SwUndoRedlineDelete::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
{
    if (rPam.GetPoint() != rPam.GetMark())
    {
        rDoc.AppendRedline( new SwRedline(*mpRedlData, rPam), sal_False );
    }
}

sal_Bool SwUndoRedlineDelete::CanGrouping( const SwUndoRedlineDelete& rNext )
{
	sal_Bool bRet = sal_False;
	if( UNDO_DELETE == mnUserId && mnUserId == rNext.mnUserId &&
		bCanGroup == rNext.bCanGroup &&
		bIsDelim == rNext.bIsDelim &&
		bIsBackspace == rNext.bIsBackspace &&
		nSttNode == nEndNode &&
		rNext.nSttNode == nSttNode &&
		rNext.nEndNode == nEndNode )
	{
		int bIsEnd = 0;
		if( rNext.nSttCntnt == nEndCntnt )
			bIsEnd = 1;
		else if( rNext.nEndCntnt == nSttCntnt )
			bIsEnd = -1;

		if( bIsEnd &&
			(( !mpRedlSaveData && !rNext.mpRedlSaveData ) ||
			 ( mpRedlSaveData && rNext.mpRedlSaveData &&
				SwUndo::CanRedlineGroup( *mpRedlSaveData,
							*rNext.mpRedlSaveData, 1 != bIsEnd )
			 )))
		{
			if( 1 == bIsEnd )
				nEndCntnt = rNext.nEndCntnt;
			else
				nSttCntnt = rNext.nSttCntnt;
			bRet = sal_True;
		}
	}
	return bRet;
}

/*  */

SwUndoRedlineSort::SwUndoRedlineSort( const SwPaM& rRange,
									const SwSortOptions& rOpt )
	: SwUndoRedline( UNDO_SORT_TXT, rRange ),
	pOpt( new SwSortOptions( rOpt ) ),
	nSaveEndNode( nEndNode ), nOffset( 0 ), nSaveEndCntnt( nEndCntnt )
{
}

SwUndoRedlineSort::~SwUndoRedlineSort()
{
	delete pOpt;
}

void SwUndoRedlineSort::UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
{
    // rPam contains the sorted range
    // aSaveRange contains copied (i.e. original) range

    SwPosition *const pStart = rPam.Start();
    SwPosition *const pEnd   = rPam.End();

	SwNodeIndex aPrevIdx( pStart->nNode, -1 );
	sal_uLong nOffsetTemp = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex();

	if( 0 == ( nsRedlineMode_t::REDLINE_SHOW_DELETE & rDoc.GetRedlineMode()) )
	{
		// die beiden Redline Objecte suchen und diese dann anzeigen lassen,
		// damit die Nodes wieder uebereinstimmen!
		// das Geloeschte ist versteckt, also suche das INSERT
		// Redline Object. Dahinter steht das Geloeschte
		sal_uInt16 nFnd = rDoc.GetRedlinePos(
							*rDoc.GetNodes()[ nSttNode + 1 ],
							nsRedlineType_t::REDLINE_INSERT );
		ASSERT( USHRT_MAX != nFnd && nFnd+1 < rDoc.GetRedlineTbl().Count(),
					"kein Insert Object gefunden" );
		++nFnd;
		rDoc.GetRedlineTbl()[nFnd]->Show( 1 );
	}

	{
        SwPaM aTmp( *rPam.GetMark() );
		aTmp.GetMark()->nContent = 0;
		aTmp.SetMark();
		aTmp.GetPoint()->nNode = nSaveEndNode;
		aTmp.GetPoint()->nContent.Assign( aTmp.GetCntntNode(), nSaveEndCntnt );
		rDoc.DeleteRedline( aTmp, true, USHRT_MAX );
	}

    rDoc.DelFullPara(rPam);

    SwPaM *const pPam = & rPam;
	pPam->DeleteMark();
	pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
	SwCntntNode* pCNd = pPam->GetCntntNode();
	pPam->GetPoint()->nContent.Assign(pCNd, 0 );
	pPam->SetMark();

	pPam->GetPoint()->nNode += nOffsetTemp;
	pCNd = pPam->GetCntntNode();
	pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );

	SetValues( *pPam );

    SetPaM(rPam);
}

void SwUndoRedlineSort::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
{
	SwPaM* pPam = &rPam;
	SwPosition* pStart = pPam->Start();
	SwPosition* pEnd   = pPam->End();

	SwNodeIndex aPrevIdx( pStart->nNode, -1 );
	sal_uLong nOffsetTemp = pEnd->nNode.GetIndex() - pStart->nNode.GetIndex();
	xub_StrLen nCntStt	= pStart->nContent.GetIndex();

    rDoc.SortText(rPam, *pOpt);

	pPam->DeleteMark();
	pPam->GetPoint()->nNode.Assign( aPrevIdx.GetNode(), +1 );
	SwCntntNode* pCNd = pPam->GetCntntNode();
	xub_StrLen nLen = pCNd->Len();
	if( nLen > nCntStt )
		nLen = nCntStt;
	pPam->GetPoint()->nContent.Assign(pCNd, nLen );
	pPam->SetMark();

	pPam->GetPoint()->nNode += nOffsetTemp;
	pCNd = pPam->GetCntntNode();
	pPam->GetPoint()->nContent.Assign( pCNd, pCNd->Len() );

	SetValues( rPam );

	SetPaM( rPam );
	rPam.GetPoint()->nNode = nSaveEndNode;
	rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), nSaveEndCntnt );
}

void SwUndoRedlineSort::RepeatImpl(::sw::RepeatContext & rContext)
{
    rContext.GetDoc().SortText( rContext.GetRepeatPaM(), *pOpt );
}

void SwUndoRedlineSort::SetSaveRange( const SwPaM& rRange )
{
	const SwPosition& rPos = *rRange.End();
	nSaveEndNode = rPos.nNode.GetIndex();
	nSaveEndCntnt = rPos.nContent.GetIndex();
}

void SwUndoRedlineSort::SetOffset( const SwNodeIndex& rIdx )
{
	nOffset = rIdx.GetIndex() - nSttNode;
}

// SwUndoAcceptRedline ///////////////////////////////////////////////////

SwUndoAcceptRedline::SwUndoAcceptRedline( const SwPaM& rRange )
	: SwUndoRedline( UNDO_ACCEPT_REDLINE, rRange )
{
}

void SwUndoAcceptRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
{
    rDoc.AcceptRedline(rPam, false);
}

void SwUndoAcceptRedline::RepeatImpl(::sw::RepeatContext & rContext)
{
    rContext.GetDoc().AcceptRedline(rContext.GetRepeatPaM(), true);
}

SwUndoRejectRedline::SwUndoRejectRedline( const SwPaM& rRange )
	: SwUndoRedline( UNDO_REJECT_REDLINE, rRange )
{
}

void SwUndoRejectRedline::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
{
    rDoc.RejectRedline(rPam, false);
}

void SwUndoRejectRedline::RepeatImpl(::sw::RepeatContext & rContext)
{
    rContext.GetDoc().RejectRedline(rContext.GetRepeatPaM(), true);
}

// SwUndoCompDoc /////////////////////////////////////////////////////////

SwUndoCompDoc::SwUndoCompDoc( const SwPaM& rRg, sal_Bool bIns )
	: SwUndo( UNDO_COMPAREDOC ), SwUndRng( rRg ), pRedlData( 0 ),
	pUnDel( 0 ), pUnDel2( 0 ), pRedlSaveData( 0 ), bInsert( bIns )
{
	SwDoc* pDoc = (SwDoc*)rRg.GetDoc();
	if( pDoc->IsRedlineOn() )
	{
		RedlineType_t eTyp = bInsert ? nsRedlineType_t::REDLINE_INSERT : nsRedlineType_t::REDLINE_DELETE;
		pRedlData = new SwRedlineData( eTyp, pDoc->GetRedlineAuthor() );
		SetRedlineMode( pDoc->GetRedlineMode() );
	}
}

SwUndoCompDoc::SwUndoCompDoc( const SwRedline& rRedl )
	: SwUndo( UNDO_COMPAREDOC ), SwUndRng( rRedl ), pRedlData( 0 ),
	pUnDel( 0 ), pUnDel2( 0 ), pRedlSaveData( 0 ),
	// fuers MergeDoc wird aber der jeweils umgekehrte Zweig benoetigt!
	bInsert( nsRedlineType_t::REDLINE_DELETE == rRedl.GetType() )
{
	SwDoc* pDoc = (SwDoc*)rRedl.GetDoc();
	if( pDoc->IsRedlineOn() )
	{
		pRedlData = new SwRedlineData( rRedl.GetRedlineData() );
		SetRedlineMode( pDoc->GetRedlineMode() );
	}

	pRedlSaveData = new SwRedlineSaveDatas;
	if( !FillSaveData( rRedl, *pRedlSaveData, sal_False, sal_True ))
		delete pRedlSaveData, pRedlSaveData = 0;
}

SwUndoCompDoc::~SwUndoCompDoc()
{
	delete pRedlData;
	delete pUnDel;
	delete pUnDel2;
	delete pRedlSaveData;
}

void SwUndoCompDoc::UndoImpl(::sw::UndoRedoContext & rContext)
{
    SwDoc *const pDoc = & rContext.GetDoc();
    SwPaM *const pPam( & AddUndoRedoPaM(rContext) );

	if( !bInsert )
	{
		// die Redlines loeschen
		RedlineMode_t eOld = pDoc->GetRedlineMode();
		pDoc->SetRedlineMode_intern((RedlineMode_t)(( eOld & ~nsRedlineMode_t::REDLINE_IGNORE) | nsRedlineMode_t::REDLINE_ON));

		pDoc->DeleteRedline( *pPam, true, USHRT_MAX );

		pDoc->SetRedlineMode_intern( eOld );

		//per definition Point is end (in SwUndRng!)
		SwCntntNode* pCSttNd = pPam->GetCntntNode( sal_False );
		SwCntntNode* pCEndNd = pPam->GetCntntNode( sal_True );

		// if start- and end-content is zero, then the doc-compare moves
		// complete nodes into the current doc. And then the selection
		// must be from end to start, so the delete join into the right
		// direction.
		if( !nSttCntnt && !nEndCntnt )
			pPam->Exchange();

		sal_Bool bJoinTxt, bJoinPrev;
		::lcl_GetJoinFlags( *pPam, bJoinTxt, bJoinPrev );

		pUnDel = new SwUndoDelete( *pPam, sal_False );

		if( bJoinTxt )
			::lcl_JoinText( *pPam, bJoinPrev );

		if( pCSttNd && !pCEndNd)
		{
            // #112139# Do not step behind the end of content.
            SwNode * pTmp = pPam->GetNode(sal_True);
            if (pTmp)
            {
                SwNode * pEnd = pDoc->GetNodes().DocumentSectionEndNode(pTmp);

                if (pTmp != pEnd)
                {
                    pPam->SetMark();
                    pPam->GetPoint()->nNode++;
                    pPam->GetBound( sal_True ).nContent.Assign( 0, 0 );
                    pPam->GetBound( sal_False ).nContent.Assign( 0, 0 );
                    pUnDel2 = new SwUndoDelete( *pPam, sal_True );
                }
            }
        }
		pPam->DeleteMark();
	}
	else
	{
		if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
		{
			pDoc->DeleteRedline( *pPam, true, USHRT_MAX );

			if( pRedlSaveData )
				SetSaveData( *pDoc, *pRedlSaveData );
		}
        SetPaM(*pPam, true);
    }
}

void SwUndoCompDoc::RedoImpl(::sw::UndoRedoContext & rContext)
{
    SwDoc *const pDoc = & rContext.GetDoc();
    SwPaM *const pPam( & AddUndoRedoPaM(rContext) );

	if( bInsert )
	{
		if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
		{
			SwRedline* pTmp = new SwRedline( *pRedlData, *pPam );
			((SwRedlineTbl&)pDoc->GetRedlineTbl()).Insert( pTmp );
			pTmp->InvalidateRange();

/*
			SwRedlineMode eOld = pDoc->GetRedlineMode();
			pDoc->SetRedlineMode_intern( eOld & ~REDLINE_IGNORE );
			pDoc->AppendRedline( new SwRedline( *pRedlData, *pPam ));
			pDoc->SetRedlineMode_intern( eOld );
*/
		}
		else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
				pDoc->GetRedlineTbl().Count() )
			pDoc->SplitRedline( *pPam );
	}
	else
	{
//		SwRedlineMode eOld = pDoc->GetRedlineMode();
//		pDoc->SetRedlineMode_intern( ( eOld & ~REDLINE_IGNORE) | REDLINE_ON );

		if( pUnDel2 )
        {
            pUnDel2->UndoImpl(rContext);
			delete pUnDel2, pUnDel2 = 0;
        }
        pUnDel->UndoImpl(rContext);
		delete pUnDel, pUnDel = 0;

		SetPaM( *pPam );

		SwRedline* pTmp = new SwRedline( *pRedlData, *pPam );
		((SwRedlineTbl&)pDoc->GetRedlineTbl()).Insert( pTmp );
        if (pTmp) // #i19649#
            pTmp->InvalidateRange();

//		pDoc->SetRedlineMode_intern( eOld );
	}

    SetPaM(*pPam, true);
}

