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

#include "scitems.hxx"
#include <editeng/eeitem.hxx>

#include <editeng/editobj.hxx>
#include <svl/zforlist.hxx>
#include <sfx2/app.hxx>

#include "undocell.hxx"
#include "document.hxx"
#include "docpool.hxx"
#include "patattr.hxx"
#include "docsh.hxx"
#include "tabvwsh.hxx"
#include "globstr.hrc"
#include "global.hxx"
#include "cell.hxx"
#include "target.hxx"
#include "undoolk.hxx"
#include "detdata.hxx"
#include "stlpool.hxx"
#include "printfun.hxx"
#include "rangenam.hxx"
#include "chgtrack.hxx"
#include "sc.hrc"
#include "docuno.hxx"

// STATIC DATA -----------------------------------------------------------

TYPEINIT1(ScUndoCursorAttr, ScSimpleUndo);
TYPEINIT1(ScUndoEnterData, ScSimpleUndo);
TYPEINIT1(ScUndoEnterValue, ScSimpleUndo);
TYPEINIT1(ScUndoPutCell, ScSimpleUndo);
TYPEINIT1(ScUndoPageBreak, ScSimpleUndo);
TYPEINIT1(ScUndoPrintZoom, ScSimpleUndo);
TYPEINIT1(ScUndoThesaurus, ScSimpleUndo);
TYPEINIT1(ScUndoReplaceNote, ScSimpleUndo);
TYPEINIT1(ScUndoShowHideNote, ScSimpleUndo);
TYPEINIT1(ScUndoDetective, ScSimpleUndo);
TYPEINIT1(ScUndoRangeNames, ScSimpleUndo);


// -----------------------------------------------------------------------
//
//		Attribute auf Cursor anwenden
//

ScUndoCursorAttr::ScUndoCursorAttr( ScDocShell* pNewDocShell,
			SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
			const ScPatternAttr* pOldPat, const ScPatternAttr* pNewPat,
			const ScPatternAttr* pApplyPat, sal_Bool bAutomatic ) :
	ScSimpleUndo( pNewDocShell ),
	nCol( nNewCol ),
	nRow( nNewRow ),
	nTab( nNewTab ),
	bIsAutomatic( bAutomatic )
{
	ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool();
	pNewPattern = (ScPatternAttr*) &pPool->Put( *pNewPat );
	pOldPattern = (ScPatternAttr*) &pPool->Put( *pOldPat );
	pApplyPattern = (ScPatternAttr*) &pPool->Put( *pApplyPat );
}

__EXPORT ScUndoCursorAttr::~ScUndoCursorAttr()
{
	ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool();
	pPool->Remove(*pNewPattern);
	pPool->Remove(*pOldPattern);
	pPool->Remove(*pApplyPattern);
}

String __EXPORT ScUndoCursorAttr::GetComment() const
{
	//!	eigener Text fuer automatische Attributierung

	sal_uInt16 nId = STR_UNDO_CURSORATTR;		 // "Attribute"
	return ScGlobal::GetRscString( nId );
}

void ScUndoCursorAttr::DoChange( const ScPatternAttr* pWhichPattern ) const
{
	pDocShell->GetDocument()->SetPattern( nCol, nRow, nTab, *pWhichPattern, sal_True );

	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
	if (pViewShell)
	{
		pViewShell->SetTabNo( nTab );
		pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, sal_False, sal_False );
		pViewShell->AdjustBlockHeight();
	}

	const SfxItemSet& rApplySet = pApplyPattern->GetItemSet();
	sal_Bool bPaintExt = ( rApplySet.GetItemState( ATTR_SHADOW, sal_True ) != SFX_ITEM_DEFAULT ||
					   rApplySet.GetItemState( ATTR_CONDITIONAL, sal_True ) != SFX_ITEM_DEFAULT );
	sal_Bool bPaintRows = ( rApplySet.GetItemState( ATTR_HOR_JUSTIFY, sal_True ) != SFX_ITEM_DEFAULT );

	sal_uInt16 nFlags = SC_PF_TESTMERGE;
	if (bPaintExt)
		nFlags |= SC_PF_LINES;
	if (bPaintRows)
		nFlags |= SC_PF_WHOLEROWS;
	pDocShell->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, nFlags );
}

void __EXPORT ScUndoCursorAttr::Undo()
{
	BeginUndo();
	DoChange(pOldPattern);

	if ( bIsAutomatic )
	{
		//	wenn automatische Formatierung rueckgaengig gemacht wird,
		//	soll auch nicht weiter automatisch formatiert werden:

		ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
		if (pViewShell)
			pViewShell->ForgetFormatArea();
	}

	EndUndo();
}

void __EXPORT ScUndoCursorAttr::Redo()
{
	BeginRedo();
	DoChange(pNewPattern);
	EndRedo();
}

void __EXPORT ScUndoCursorAttr::Repeat(SfxRepeatTarget& rTarget)
{
	if (rTarget.ISA(ScTabViewTarget))
		((ScTabViewTarget&)rTarget).GetViewShell()->ApplySelectionPattern( *pApplyPattern );
}

sal_Bool __EXPORT ScUndoCursorAttr::CanRepeat(SfxRepeatTarget& rTarget) const
{
	return (rTarget.ISA(ScTabViewTarget));
}


// -----------------------------------------------------------------------
//
//		Daten eingeben
//

ScUndoEnterData::ScUndoEnterData( ScDocShell* pNewDocShell,
			SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
			SCTAB nNewCount, SCTAB* pNewTabs, ScBaseCell** ppOldData,
			sal_Bool* pHasForm, sal_uLong* pOldForm,
			const String& rNewStr, EditTextObject* pObj ) :
	ScSimpleUndo( pNewDocShell ),
	aNewString( rNewStr ),
	pTabs( pNewTabs ),
	ppOldCells( ppOldData ),
	pHasFormat( pHasForm ),
	pOldFormats( pOldForm ),
	pNewEditData( pObj ),
	nCol( nNewCol ),
	nRow( nNewRow ),
	nTab( nNewTab ),
	nCount( nNewCount )
{
	SetChangeTrack();
}

__EXPORT ScUndoEnterData::~ScUndoEnterData()
{
	for (sal_uInt16 i=0; i<nCount; i++)
		if (ppOldCells[i])
			ppOldCells[i]->Delete();
	delete[] ppOldCells;

	delete[] pHasFormat;
	delete[] pOldFormats;
	delete[] pTabs;

	delete pNewEditData;
}

String __EXPORT ScUndoEnterData::GetComment() const
{
	return ScGlobal::GetRscString( STR_UNDO_ENTERDATA ); // "Eingabe"
}

void ScUndoEnterData::DoChange() const
{
	//	Zeilenhoehe anpassen
	//!	nur wenn noetig (alte oder neue EditZelle, oder Attribute) ??
	for (sal_uInt16 i=0; i<nCount; i++)
		pDocShell->AdjustRowHeight( nRow, nRow, pTabs[i] );

	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
	if (pViewShell)
	{
		pViewShell->SetTabNo( nTab );
		pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, sal_False, sal_False );
	}

	pDocShell->PostDataChanged();
}

void ScUndoEnterData::SetChangeTrack()
{
	ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
	if ( pChangeTrack )
	{
		nEndChangeAction = pChangeTrack->GetActionMax() + 1;
		ScAddress aPos( nCol, nRow, nTab );
		for (sal_uInt16 i=0; i<nCount; i++)
		{
			aPos.SetTab( pTabs[i] );
			sal_uLong nFormat = 0;
			if ( pHasFormat && pOldFormats )
			{
				if ( pHasFormat[i] )
					nFormat = pOldFormats[i];
			}
			pChangeTrack->AppendContent( aPos, ppOldCells[i], nFormat );
		}
		if ( nEndChangeAction > pChangeTrack->GetActionMax() )
			nEndChangeAction = 0;		// nichts appended
	}
	else
		nEndChangeAction = 0;
}

void __EXPORT ScUndoEnterData::Undo()
{
	BeginUndo();

	ScDocument* pDoc = pDocShell->GetDocument();
	for (sal_uInt16 i=0; i<nCount; i++)
	{
        ScBaseCell* pNewCell = ppOldCells[i] ? ppOldCells[i]->CloneWithoutNote( *pDoc, SC_CLONECELL_STARTLISTENING ) : 0;
		pDoc->PutCell( nCol, nRow, pTabs[i], pNewCell );

		if (pHasFormat && pOldFormats)
		{
			if ( pHasFormat[i] )
				pDoc->ApplyAttr( nCol, nRow, pTabs[i],
									SfxUInt32Item( ATTR_VALUE_FORMAT, pOldFormats[i] ) );
			else
			{
				ScPatternAttr aPattern( *pDoc->GetPattern( nCol, nRow, pTabs[i] ) );
				aPattern.GetItemSet().ClearItem( ATTR_VALUE_FORMAT );
				pDoc->SetPattern( nCol, nRow, pTabs[i], aPattern, sal_True );
			}
		}
		pDocShell->PostPaintCell( nCol, nRow, pTabs[i] );
	}

	ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
    if ( pChangeTrack && nEndChangeAction >= sal::static_int_cast<sal_uLong>(nCount) )
		pChangeTrack->Undo( nEndChangeAction - nCount + 1, nEndChangeAction );

	DoChange();
	EndUndo();

    // #i97876# Spreadsheet data changes are not notified
    ScModelObj* pModelObj = ScModelObj::getImplementation( pDocShell->GetModel() );
    if ( pModelObj && pModelObj->HasChangesListeners() )
    {
        ScRangeList aChangeRanges;
        for ( sal_uInt16 i = 0; i < nCount; ++i )
        {
            aChangeRanges.Append( ScRange( nCol, nRow, pTabs[i] ) );
        }
        pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
    }
}

void __EXPORT ScUndoEnterData::Redo()
{
	BeginRedo();

	ScDocument* pDoc = pDocShell->GetDocument();
	for (sal_uInt16 i=0; i<nCount; i++)
	{
		if (pNewEditData)
			pDoc->PutCell( nCol, nRow, pTabs[i], new ScEditCell( pNewEditData,
				pDoc, NULL ) );
		else
			pDoc->SetString( nCol, nRow, pTabs[i], aNewString );
		pDocShell->PostPaintCell( nCol, nRow, pTabs[i] );
	}

	SetChangeTrack();

	DoChange();
	EndRedo();

    // #i97876# Spreadsheet data changes are not notified
    ScModelObj* pModelObj = ScModelObj::getImplementation( pDocShell->GetModel() );
    if ( pModelObj && pModelObj->HasChangesListeners() )
    {
        ScRangeList aChangeRanges;
        for ( sal_uInt16 i = 0; i < nCount; ++i )
        {
            aChangeRanges.Append( ScRange( nCol, nRow, pTabs[i] ) );
        }
        pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
    }
}

void __EXPORT ScUndoEnterData::Repeat(SfxRepeatTarget& rTarget)
{
	if (rTarget.ISA(ScTabViewTarget))
	{
		String aTemp = aNewString;
		((ScTabViewTarget&)rTarget).GetViewShell()->EnterDataAtCursor( aTemp );
	}
}

sal_Bool __EXPORT ScUndoEnterData::CanRepeat(SfxRepeatTarget& rTarget) const
{
	return (rTarget.ISA(ScTabViewTarget));
}


// -----------------------------------------------------------------------
//
//		Wert aendern
//

ScUndoEnterValue::ScUndoEnterValue( ScDocShell* pNewDocShell, const ScAddress& rNewPos,
									ScBaseCell* pUndoCell, double nVal, sal_Bool bHeight ) :
	ScSimpleUndo( pNewDocShell ),
	aPos		( rNewPos ),
	pOldCell	( pUndoCell ),
	nValue		( nVal ),
	bNeedHeight	( bHeight )
{
	SetChangeTrack();
}

__EXPORT ScUndoEnterValue::~ScUndoEnterValue()
{
	if (pOldCell)
		pOldCell->Delete();
}

String __EXPORT ScUndoEnterValue::GetComment() const
{
	return ScGlobal::GetRscString( STR_UNDO_ENTERDATA ); // "Eingabe"
}

void ScUndoEnterValue::SetChangeTrack()
{
	ScDocument* pDoc = pDocShell->GetDocument();
	ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
	if ( pChangeTrack )
	{
		nEndChangeAction = pChangeTrack->GetActionMax() + 1;
		pChangeTrack->AppendContent( aPos, pOldCell );
		if ( nEndChangeAction > pChangeTrack->GetActionMax() )
			nEndChangeAction = 0;		// nichts appended
	}
	else
		nEndChangeAction = 0;
}

void __EXPORT ScUndoEnterValue::Undo()
{
	BeginUndo();

	ScDocument* pDoc = pDocShell->GetDocument();
    ScBaseCell* pNewCell = pOldCell ? pOldCell->CloneWithoutNote( *pDoc, SC_CLONECELL_STARTLISTENING ) : 0;

	pDoc->PutCell( aPos, pNewCell );

	pDocShell->PostPaintCell( aPos );

	ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
	if ( pChangeTrack )
		pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );

	EndUndo();
}

void __EXPORT ScUndoEnterValue::Redo()
{
	BeginRedo();

	ScDocument* pDoc = pDocShell->GetDocument();
	pDoc->SetValue( aPos.Col(), aPos.Row(), aPos.Tab(), nValue );
	pDocShell->PostPaintCell( aPos );

	SetChangeTrack();

	EndRedo();
}

void __EXPORT ScUndoEnterValue::Repeat(SfxRepeatTarget& /* rTarget */)
{
	//	gippsnich
}

sal_Bool __EXPORT ScUndoEnterValue::CanRepeat(SfxRepeatTarget& /* rTarget */) const
{
	return sal_False;
}


// -----------------------------------------------------------------------
//
//		Beliebige Zelle eingeben
//

ScUndoPutCell::ScUndoPutCell( ScDocShell* pNewDocShell, const ScAddress& rNewPos,
							ScBaseCell* pUndoCell, ScBaseCell* pRedoCell, sal_Bool bHeight ) :
	ScSimpleUndo( pNewDocShell ),
	aPos		( rNewPos ),
	pOldCell	( pUndoCell ),
	pEnteredCell( pRedoCell ),
	bNeedHeight	( bHeight )
{
	SetChangeTrack();
}

__EXPORT ScUndoPutCell::~ScUndoPutCell()
{
	if (pOldCell)
		pOldCell->Delete();
	if (pEnteredCell)
		pEnteredCell->Delete();
}

String __EXPORT ScUndoPutCell::GetComment() const
{
	return ScGlobal::GetRscString( STR_UNDO_ENTERDATA ); // "Eingabe"
}

void ScUndoPutCell::SetChangeTrack()
{
	ScDocument* pDoc = pDocShell->GetDocument();
	ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
	if ( pChangeTrack )
	{
		nEndChangeAction = pChangeTrack->GetActionMax() + 1;
		pChangeTrack->AppendContent( aPos, pOldCell );
		if ( nEndChangeAction > pChangeTrack->GetActionMax() )
			nEndChangeAction = 0;		// nichts appended
	}
	else
		nEndChangeAction = 0;
}

void __EXPORT ScUndoPutCell::Undo()
{
	BeginUndo();

	ScDocument* pDoc = pDocShell->GetDocument();
    ScBaseCell* pNewCell = pOldCell ? pOldCell->CloneWithoutNote( *pDoc, aPos, SC_CLONECELL_STARTLISTENING ) : 0;

	pDoc->PutCell( aPos.Col(), aPos.Row(), aPos.Tab(), pNewCell );

	pDocShell->PostPaintCell( aPos );

	ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
	if ( pChangeTrack )
		pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );

	EndUndo();
}

void __EXPORT ScUndoPutCell::Redo()
{
	BeginRedo();

	ScDocument* pDoc = pDocShell->GetDocument();
    ScBaseCell* pNewCell = pEnteredCell ? pEnteredCell->CloneWithoutNote( *pDoc, aPos, SC_CLONECELL_STARTLISTENING ) : 0;

	pDoc->PutCell( aPos.Col(), aPos.Row(), aPos.Tab(), pNewCell );

	pDocShell->PostPaintCell( aPos );

	SetChangeTrack();

	EndRedo();
}

void __EXPORT ScUndoPutCell::Repeat(SfxRepeatTarget& /* rTarget */)
{
	//	gippsnich
}

sal_Bool __EXPORT ScUndoPutCell::CanRepeat(SfxRepeatTarget& /* rTarget */) const
{
	return sal_False;
}


// -----------------------------------------------------------------------
//
//		Seitenumbrueche
//

ScUndoPageBreak::ScUndoPageBreak( ScDocShell* pNewDocShell,
			SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
			sal_Bool bNewColumn, sal_Bool bNewInsert ) :
	ScSimpleUndo( pNewDocShell ),
	nCol( nNewCol ),
	nRow( nNewRow ),
	nTab( nNewTab ),
	bColumn( bNewColumn ),
	bInsert( bNewInsert )
{
}

__EXPORT ScUndoPageBreak::~ScUndoPageBreak()
{
}

String __EXPORT ScUndoPageBreak::GetComment() const
{
	//"Spaltenumbruch" | "Zeilenumbruch"  "einfuegen" | "loeschen"
	return String ( bColumn ?
		( bInsert ?
			ScGlobal::GetRscString( STR_UNDO_INSCOLBREAK ) :
			ScGlobal::GetRscString( STR_UNDO_DELCOLBREAK )
		) :
		( bInsert ?
			ScGlobal::GetRscString( STR_UNDO_INSROWBREAK ) :
			ScGlobal::GetRscString( STR_UNDO_DELROWBREAK )
		) );
}

void ScUndoPageBreak::DoChange( sal_Bool bInsertP ) const
{
	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();

	if (pViewShell)
	{
		pViewShell->SetTabNo( nTab );
		pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, sal_False, sal_False );

        if (bInsertP)
			pViewShell->InsertPageBreak(bColumn, sal_False);
		else
			pViewShell->DeletePageBreak(bColumn, sal_False);

        pDocShell->GetDocument()->InvalidatePageBreaks(nTab);
	}
}

void __EXPORT ScUndoPageBreak::Undo()
{
	BeginUndo();
	DoChange(!bInsert);
	EndUndo();
}

void __EXPORT ScUndoPageBreak::Redo()
{
	BeginRedo();
	DoChange(bInsert);
	EndRedo();
}

void __EXPORT ScUndoPageBreak::Repeat(SfxRepeatTarget& rTarget)
{
	if (rTarget.ISA(ScTabViewTarget))
	{
		ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell();

		if (bInsert)
			rViewShell.InsertPageBreak(bColumn, sal_True);
		else
			rViewShell.DeletePageBreak(bColumn, sal_True);
	}
}

sal_Bool __EXPORT ScUndoPageBreak::CanRepeat(SfxRepeatTarget& rTarget) const
{
	return (rTarget.ISA(ScTabViewTarget));
}

// -----------------------------------------------------------------------
//
//		Druck-Skalierung
//

ScUndoPrintZoom::ScUndoPrintZoom( ScDocShell* pNewDocShell,
			SCTAB nT, sal_uInt16 nOS, sal_uInt16 nOP, sal_uInt16 nNS, sal_uInt16 nNP ) :
	ScSimpleUndo( pNewDocShell ),
	nTab( nT ),
	nOldScale( nOS ),
	nOldPages( nOP ),
	nNewScale( nNS ),
	nNewPages( nNP )
{
}

__EXPORT ScUndoPrintZoom::~ScUndoPrintZoom()
{
}

String __EXPORT ScUndoPrintZoom::GetComment() const
{
	return ScGlobal::GetRscString( STR_UNDO_PRINTSCALE );
}

void ScUndoPrintZoom::DoChange( sal_Bool bUndo )
{
	sal_uInt16 nScale = bUndo ? nOldScale : nNewScale;
	sal_uInt16 nPages = bUndo ? nOldPages : nNewPages;

	ScDocument* pDoc = pDocShell->GetDocument();
	String aStyleName = pDoc->GetPageStyle( nTab );
	ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
	SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
	DBG_ASSERT( pStyleSheet, "PageStyle not found" );
	if ( pStyleSheet )
	{
		SfxItemSet& rSet = pStyleSheet->GetItemSet();
		rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nScale ) );
		rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, nPages ) );

		ScPrintFunc aPrintFunc( pDocShell, pDocShell->GetPrinter(), nTab );
		aPrintFunc.UpdatePages();
	}
}

void __EXPORT ScUndoPrintZoom::Undo()
{
	BeginUndo();
	DoChange(sal_True);
	EndUndo();
}

void __EXPORT ScUndoPrintZoom::Redo()
{
	BeginRedo();
	DoChange(sal_False);
	EndRedo();
}

void __EXPORT ScUndoPrintZoom::Repeat(SfxRepeatTarget& rTarget)
{
	if (rTarget.ISA(ScTabViewTarget))
	{
		ScTabViewShell& rViewShell = *((ScTabViewTarget&)rTarget).GetViewShell();
		ScViewData* pViewData = rViewShell.GetViewData();
		pViewData->GetDocShell()->SetPrintZoom( pViewData->GetTabNo(), nNewScale, nNewPages );
	}
}

sal_Bool __EXPORT ScUndoPrintZoom::CanRepeat(SfxRepeatTarget& rTarget) const
{
	return (rTarget.ISA(ScTabViewTarget));
}


// -----------------------------------------------------------------------
//
//		Thesaurus
//

ScUndoThesaurus::ScUndoThesaurus( ScDocShell* pNewDocShell,
								  SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab,
								  const String& rNewUndoStr, const EditTextObject* pUndoTObj,
								  const String& rNewRedoStr, const EditTextObject* pRedoTObj) :
	ScSimpleUndo( pNewDocShell ),
	nCol( nNewCol ),
	nRow( nNewRow ),
	nTab( nNewTab ),
	aUndoStr( rNewUndoStr ),
	aRedoStr( rNewRedoStr )
{
	pUndoTObject = (pUndoTObj) ? pUndoTObj->Clone() : NULL;
	pRedoTObject = (pRedoTObj) ? pRedoTObj->Clone() : NULL;

	ScBaseCell* pOldCell;
	if ( pUndoTObject )
		pOldCell = new ScEditCell( pUndoTObject, pDocShell->GetDocument(), NULL );
	else
		pOldCell = new ScStringCell( aUndoStr );
	SetChangeTrack( pOldCell );
	pOldCell->Delete();
}

__EXPORT ScUndoThesaurus::~ScUndoThesaurus()
{
	delete pUndoTObject;
	delete pRedoTObject;
}

String __EXPORT ScUndoThesaurus::GetComment() const
{
	return ScGlobal::GetRscString( STR_UNDO_THESAURUS );	// "Thesaurus"
}

void ScUndoThesaurus::SetChangeTrack( ScBaseCell* pOldCell )
{
	ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
	if ( pChangeTrack )
	{
		nEndChangeAction = pChangeTrack->GetActionMax() + 1;
		pChangeTrack->AppendContent( ScAddress( nCol, nRow, nTab ), pOldCell );
		if ( nEndChangeAction > pChangeTrack->GetActionMax() )
			nEndChangeAction = 0;		// nichts appended
	}
	else
		nEndChangeAction = 0;
}

void __EXPORT ScUndoThesaurus::DoChange( sal_Bool bUndo, const String& rStr,
			const EditTextObject* pTObj )
{
	ScDocument* pDoc = pDocShell->GetDocument();

	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
	if (pViewShell)
	{
		pViewShell->SetTabNo( nTab );
		pViewShell->MoveCursorAbs( nCol, nRow, SC_FOLLOW_JUMP, sal_False, sal_False );
	}

	if (pTObj)
	{
		ScBaseCell* pCell;
		pDoc->GetCell( nCol, nRow, nTab, pCell );
		if (pCell)
		{
			if (pCell->GetCellType() == CELLTYPE_EDIT )
			{
				ScEditCell* pNewCell = new ScEditCell( pTObj, pDoc, NULL );
				pDoc->PutCell( nCol, nRow, nTab, pNewCell );
				if ( !bUndo )
					SetChangeTrack( pCell );
			}
			else
			{
				DBG_ERROR("Nicht CELLTYPE_EDIT bei Un/RedoThesaurus");
			}
		}
	}
	else
	{
        ScBaseCell* pCell = NULL;
		if ( !bUndo )
			pDoc->GetCell( nCol, nRow, nTab, pCell );
		pDoc->SetString( nCol, nRow, nTab, rStr );
		if ( !bUndo )
			SetChangeTrack( pCell );
	}

	pDocShell->PostPaintCell( nCol, nRow, nTab );
}

void __EXPORT ScUndoThesaurus::Undo()
{
	BeginUndo();
	DoChange( sal_True, aUndoStr, pUndoTObject );
	ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack();
	if ( pChangeTrack )
		pChangeTrack->Undo( nEndChangeAction, nEndChangeAction );
	EndUndo();
}

void __EXPORT ScUndoThesaurus::Redo()
{
	BeginRedo();
	DoChange( sal_False, aRedoStr, pRedoTObject );
	EndRedo();
}

void __EXPORT ScUndoThesaurus::Repeat(SfxRepeatTarget& rTarget)
{
	if (rTarget.ISA(ScTabViewTarget))
		((ScTabViewTarget&)rTarget).GetViewShell()->DoThesaurus( sal_True );
}

sal_Bool __EXPORT ScUndoThesaurus::CanRepeat(SfxRepeatTarget& rTarget) const
{
	return (rTarget.ISA(ScTabViewTarget));
}


// ============================================================================

ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos,
        const ScNoteData& rNoteData, bool bInsert, SdrUndoAction* pDrawUndo ) :
    ScSimpleUndo( &rDocShell ),
    maPos( rPos ),
    mpDrawUndo( pDrawUndo )
{
    DBG_ASSERT( rNoteData.mpCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note caption" );
    (bInsert ? maNewData : maOldData) = rNoteData;
}

ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rPos,
        const ScNoteData& rOldData, const ScNoteData& rNewData, SdrUndoAction* pDrawUndo ) :
    ScSimpleUndo( &rDocShell ),
    maPos( rPos ),
    maOldData( rOldData ),
    maNewData( rNewData ),
    mpDrawUndo( pDrawUndo )
{
    DBG_ASSERT( maOldData.mpCaption || maNewData.mpCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note captions" );
    DBG_ASSERT( !maOldData.mxInitData.get() && !maNewData.mxInitData.get(), "ScUndoReplaceNote::ScUndoReplaceNote - unexpected unitialized note" );
}

ScUndoReplaceNote::~ScUndoReplaceNote()
{
    DeleteSdrUndoAction( mpDrawUndo );
}

void ScUndoReplaceNote::Undo()
{
	BeginUndo();
    DoSdrUndoAction( mpDrawUndo, pDocShell->GetDocument() );
    /*  Undo insert -> remove new note.
        Undo remove -> insert old note.
        Undo replace -> remove new note, insert old note. */
    DoRemoveNote( maNewData );
    DoInsertNote( maOldData );
    pDocShell->PostPaintCell( maPos );
	EndUndo();
}

void ScUndoReplaceNote::Redo()
{
	BeginRedo();
    RedoSdrUndoAction( mpDrawUndo );
    /*  Redo insert -> insert new note.
        Redo remove -> remove old note.
        Redo replace -> remove old note, insert new note. */
    DoRemoveNote( maOldData );
    DoInsertNote( maNewData );
    pDocShell->PostPaintCell( maPos );
	EndRedo();
}

void ScUndoReplaceNote::Repeat( SfxRepeatTarget& /*rTarget*/ )
{
}

sal_Bool ScUndoReplaceNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
{
	return sal_False;
}

String ScUndoReplaceNote::GetComment() const
{
    return ScGlobal::GetRscString( maNewData.mpCaption ?
        (maOldData.mpCaption ? STR_UNDO_EDITNOTE : STR_UNDO_INSERTNOTE) : STR_UNDO_DELETENOTE );
}

void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData )
{
    if( rNoteData.mpCaption )
    {
        ScDocument& rDoc = *pDocShell->GetDocument();
        DBG_ASSERT( !rDoc.GetNote( maPos ), "ScUndoReplaceNote::DoInsertNote - unexpected cell note" );
        ScPostIt* pNote = new ScPostIt( rDoc, maPos, rNoteData, false );
        rDoc.TakeNote( maPos, pNote );
    }
}

void ScUndoReplaceNote::DoRemoveNote( const ScNoteData& rNoteData )
{
    if( rNoteData.mpCaption )
    {
        ScDocument& rDoc = *pDocShell->GetDocument();
        DBG_ASSERT( rDoc.GetNote( maPos ), "ScUndoReplaceNote::DoRemoveNote - missing cell note" );
        if( ScPostIt* pNote = rDoc.ReleaseNote( maPos ) )
        {
            /*  Forget pointer to caption object to suppress removing the
                caption object from the drawing layer while deleting pNote
                (removing the caption is done by a drawing undo action). */
            pNote->ForgetCaption();
            delete pNote;
        }
    }
}

// ============================================================================

ScUndoShowHideNote::ScUndoShowHideNote( ScDocShell& rDocShell, const ScAddress& rPos, bool bShow ) :
	ScSimpleUndo( &rDocShell ),
	maPos( rPos ),
	mbShown( bShow )
{
}

ScUndoShowHideNote::~ScUndoShowHideNote()
{
}

void ScUndoShowHideNote::Undo()
{
	BeginUndo();
	if( ScPostIt* pNote = pDocShell->GetDocument()->GetNote( maPos ) )
        pNote->ShowCaption( maPos, !mbShown );
	EndUndo();
}

void ScUndoShowHideNote::Redo()
{
	BeginRedo();
	if( ScPostIt* pNote = pDocShell->GetDocument()->GetNote( maPos ) )
        pNote->ShowCaption( maPos, mbShown );
	EndRedo();
}

void ScUndoShowHideNote::Repeat( SfxRepeatTarget& /*rTarget*/ )
{
}

sal_Bool ScUndoShowHideNote::CanRepeat( SfxRepeatTarget& /*rTarget*/ ) const
{
	return sal_False;
}

String ScUndoShowHideNote::GetComment() const
{
    return ScGlobal::GetRscString( mbShown ? STR_UNDO_SHOWNOTE : STR_UNDO_HIDENOTE );
}

// ============================================================================

// -----------------------------------------------------------------------
//
//		Detektiv
//

ScUndoDetective::ScUndoDetective( ScDocShell* pNewDocShell,
									SdrUndoAction* pDraw, const ScDetOpData* pOperation,
									ScDetOpList* pUndoList ) :
	ScSimpleUndo( pNewDocShell ),
	pOldList	( pUndoList ),
	nAction		( 0 ),
	pDrawUndo	( pDraw )
{
	bIsDelete = ( pOperation == NULL );
	if (!bIsDelete)
	{
		nAction = (sal_uInt16) pOperation->GetOperation();
		aPos = pOperation->GetPos();
	}
}

__EXPORT ScUndoDetective::~ScUndoDetective()
{
	DeleteSdrUndoAction( pDrawUndo );
	delete pOldList;
}

String __EXPORT ScUndoDetective::GetComment() const
{
	sal_uInt16 nId = STR_UNDO_DETDELALL;
	if ( !bIsDelete )
		switch ( (ScDetOpType) nAction )
		{
			case SCDETOP_ADDSUCC:	nId = STR_UNDO_DETADDSUCC;	break;
			case SCDETOP_DELSUCC:	nId = STR_UNDO_DETDELSUCC;	break;
			case SCDETOP_ADDPRED:	nId = STR_UNDO_DETADDPRED;	break;
			case SCDETOP_DELPRED:	nId = STR_UNDO_DETDELPRED;	break;
			case SCDETOP_ADDERROR:	nId = STR_UNDO_DETADDERROR;	break;
		}

	return ScGlobal::GetRscString( nId );
}


void __EXPORT ScUndoDetective::Undo()
{
	BeginUndo();

	ScDocument* pDoc = pDocShell->GetDocument();
    DoSdrUndoAction(pDrawUndo, pDoc);

	if (bIsDelete)
	{
		if ( pOldList )
			pDoc->SetDetOpList( new ScDetOpList(*pOldList) );
	}
	else
	{
		//	Eintrag aus der Liste loeschen

		ScDetOpList* pList = pDoc->GetDetOpList();
		if (pList && pList->Count())
		{
			sal_uInt16 nPos = pList->Count() - 1;
			ScDetOpData* pData = (*pList)[nPos];
			if ( pData->GetOperation() == (ScDetOpType) nAction && pData->GetPos() == aPos )
				pList->DeleteAndDestroy( nPos, 1 );
			else
			{
				DBG_ERROR("Detektiv-Eintrag in der Liste nicht gefunden");
			}
		}
	}

	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
	if (pViewShell)
		pViewShell->RecalcPPT();	//! use broadcast instead?

	EndUndo();
}

void __EXPORT ScUndoDetective::Redo()
{
	BeginRedo();

    RedoSdrUndoAction(pDrawUndo);

	ScDocument* pDoc = pDocShell->GetDocument();

	if (bIsDelete)
		pDoc->ClearDetectiveOperations();
	else
		pDoc->AddDetectiveOperation( ScDetOpData( aPos, (ScDetOpType) nAction ) );

	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
	if (pViewShell)
		pViewShell->RecalcPPT();	//! use broadcast instead?

	EndRedo();
}

void __EXPORT ScUndoDetective::Repeat(SfxRepeatTarget& /* rTarget */)
{
	//	hammanich
}

sal_Bool __EXPORT ScUndoDetective::CanRepeat(SfxRepeatTarget& /* rTarget */) const
{
	return sal_False;
}

// -----------------------------------------------------------------------
//
//		Benannte Bereiche
//

ScUndoRangeNames::ScUndoRangeNames( ScDocShell* pNewDocShell,
									ScRangeName* pOld, ScRangeName* pNew ) :
	ScSimpleUndo( pNewDocShell ),
	pOldRanges	( pOld ),
	pNewRanges	( pNew )
{
}

__EXPORT ScUndoRangeNames::~ScUndoRangeNames()
{
	delete pOldRanges;
	delete pNewRanges;
}

String __EXPORT ScUndoRangeNames::GetComment() const
{
	return ScGlobal::GetRscString( STR_UNDO_RANGENAMES );
}

void ScUndoRangeNames::DoChange( sal_Bool bUndo )
{
	ScDocument* pDoc = pDocShell->GetDocument();
	pDoc->CompileNameFormula( sal_True );	// CreateFormulaString

	if ( bUndo )
		pDoc->SetRangeName( new ScRangeName( *pOldRanges ) );
	else
		pDoc->SetRangeName( new ScRangeName( *pNewRanges ) );

	pDoc->CompileNameFormula( sal_False );	// CompileFormulaString

	SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
}

void __EXPORT ScUndoRangeNames::Undo()
{
	BeginUndo();
	DoChange( sal_True );
	EndUndo();
}

void __EXPORT ScUndoRangeNames::Redo()
{
	BeginRedo();
	DoChange( sal_False );
	EndRedo();
}

void __EXPORT ScUndoRangeNames::Repeat(SfxRepeatTarget& /* rTarget */)
{
	//	hammanich
}

sal_Bool __EXPORT ScUndoRangeNames::CanRepeat(SfxRepeatTarget& /* rTarget */) const
{
	return sal_False;
}




