diff options
Diffstat (limited to 'sc/inc/chgtrack.hxx')
-rw-r--r-- | sc/inc/chgtrack.hxx | 1370 |
1 files changed, 1370 insertions, 0 deletions
diff --git a/sc/inc/chgtrack.hxx b/sc/inc/chgtrack.hxx new file mode 100644 index 000000000000..6cf3d59314ef --- /dev/null +++ b/sc/inc/chgtrack.hxx @@ -0,0 +1,1370 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SC_CHGTRACK_HXX +#define SC_CHGTRACK_HXX + + +#include <tools/string.hxx> +#include <tools/datetime.hxx> +#include <tools/table.hxx> +#include <tools/stack.hxx> +#include <tools/queue.hxx> +#include <tools/mempool.hxx> +#include <tools/link.hxx> +#include <unotools/options.hxx> +#include "global.hxx" +#include "bigrange.hxx" +#include "collect.hxx" +#include "scdllapi.h" + +#ifdef SC_CHGTRACK_CXX +// core/inc +#include "refupdat.hxx" +#endif + +#define DEBUG_CHANGETRACK 0 + + +class ScBaseCell; +class ScDocument; + + +enum ScChangeActionType +{ + SC_CAT_NONE, + SC_CAT_INSERT_COLS, + SC_CAT_INSERT_ROWS, + SC_CAT_INSERT_TABS, + SC_CAT_DELETE_COLS, + SC_CAT_DELETE_ROWS, + SC_CAT_DELETE_TABS, + SC_CAT_MOVE, + SC_CAT_CONTENT, + SC_CAT_REJECT +}; + + +enum ScChangeActionState +{ + SC_CAS_VIRGIN, + SC_CAS_ACCEPTED, + SC_CAS_REJECTED +}; + + +enum ScChangeActionClipMode +{ + SC_CACM_NONE, + SC_CACM_CUT, + SC_CACM_COPY, + SC_CACM_PASTE +}; + +class SvStream; + +// --- ScChangeActionLinkEntry --------------------------------------------- + +// Fuegt sich selbst am Beginn einer Kette ein, bzw. vor einem anderen +// LinkEntry, on delete selbstaendiges ausklinken auch des gelinkten. +// ppPrev == &previous->pNext oder Adresse des Pointers auf Beginn der Kette, +// *ppPrev == this + +class ScChangeAction; + +class ScChangeActionLinkEntry +{ + // not implemented, prevent usage + ScChangeActionLinkEntry( + const ScChangeActionLinkEntry& ); + ScChangeActionLinkEntry& operator=( const ScChangeActionLinkEntry& ); + +protected: + + ScChangeActionLinkEntry* pNext; + ScChangeActionLinkEntry** ppPrev; + ScChangeAction* pAction; + ScChangeActionLinkEntry* pLink; + +public: + + DECL_FIXEDMEMPOOL_NEWDEL( ScChangeActionLinkEntry ) + + ScChangeActionLinkEntry( + ScChangeActionLinkEntry** ppPrevP, + ScChangeAction* pActionP ) + : pNext( *ppPrevP ), + ppPrev( ppPrevP ), + pAction( pActionP ), + pLink( NULL ) + { + if ( pNext ) + pNext->ppPrev = &pNext; + *ppPrevP = this; + } + + virtual ~ScChangeActionLinkEntry() + { + ScChangeActionLinkEntry* p = pLink; + UnLink(); + Remove(); + if ( p ) + delete p; + } + + void SetLink( ScChangeActionLinkEntry* pLinkP ) + { + UnLink(); + if ( pLinkP ) + { + pLink = pLinkP; + pLinkP->pLink = this; + } + } + + void UnLink() + { + if ( pLink ) + { + pLink->pLink = NULL; + pLink = NULL; + } + } + + void Remove() + { + if ( ppPrev ) + { + if ( ( *ppPrev = pNext ) != NULL ) + pNext->ppPrev = ppPrev; + ppPrev = NULL; // not inserted + } + } + + void Insert( ScChangeActionLinkEntry** ppPrevP ) + { + if ( !ppPrev ) + { + ppPrev = ppPrevP; + if ( (pNext = *ppPrevP) ) + pNext->ppPrev = &pNext; + *ppPrevP = this; + } + } + + const ScChangeActionLinkEntry* GetLink() const { return pLink; } + ScChangeActionLinkEntry* GetLink() { return pLink; } + const ScChangeActionLinkEntry* GetNext() const { return pNext; } + ScChangeActionLinkEntry* GetNext() { return pNext; } + const ScChangeAction* GetAction() const { return pAction; } + ScChangeAction* GetAction() { return pAction; } +#if DEBUG_CHANGETRACK + String ToString() const; +#endif // DEBUG_CHANGETRACK +}; + +// --- ScChangeActionCellListEntry ----------------------------------------- +// this is only for the XML Export in the hxx +class ScChangeActionContent; + +class ScChangeActionCellListEntry +{ + friend class ScChangeAction; + friend class ScChangeActionDel; + friend class ScChangeActionMove; + friend class ScChangeTrack; + + ScChangeActionCellListEntry* pNext; + ScChangeActionContent* pContent; + + ScChangeActionCellListEntry( + ScChangeActionContent* pContentP, + ScChangeActionCellListEntry* pNextP ) + : pNext( pNextP ), + pContent( pContentP ) + {} + +public: + const ScChangeActionCellListEntry* GetNext() const { return pNext; } // this is only for the XML Export public + const ScChangeActionContent* GetContent() const { return pContent; } // this is only for the XML Export public + + DECL_FIXEDMEMPOOL_NEWDEL( ScChangeActionCellListEntry ) +}; + +// --- ScChangeAction ------------------------------------------------------- + +class ScChangeTrack; +class ScChangeActionIns; +class ScChangeActionDel; +class ScChangeActionContent; + +class ScChangeAction +{ + friend class ScChangeTrack; + friend class ScChangeActionIns; + friend class ScChangeActionDel; + friend class ScChangeActionMove; + friend class ScChangeActionContent; + + // not implemented, prevent usage + ScChangeAction( const ScChangeAction& ); + ScChangeAction& operator=( const ScChangeAction& ); + +protected: + + ScBigRange aBigRange; // Ins/Del/MoveTo/ContentPos + DateTime aDateTime; //! UTC + String aUser; // wer war's + String aComment; // Benutzerkommentar + ScChangeAction* pNext; // naechster in Kette + ScChangeAction* pPrev; // vorheriger in Kette + ScChangeActionLinkEntry* pLinkAny; // irgendwelche Links + ScChangeActionLinkEntry* pLinkDeletedIn; // Zuordnung zu + // geloeschten oder + // druebergemoveten oder + // rejecteten Insert + // Bereichen + ScChangeActionLinkEntry* pLinkDeleted; // Links zu geloeschten + ScChangeActionLinkEntry* pLinkDependent; // Links zu abhaengigen + ULONG nAction; + ULONG nRejectAction; + ScChangeActionType eType; + ScChangeActionState eState; + + + ScChangeAction( ScChangeActionType, + const ScRange& ); + + // only to be used in the XML import + ScChangeAction( ScChangeActionType, + const ScBigRange&, + const ULONG nAction, + const ULONG nRejectAction, + const ScChangeActionState eState, + const DateTime& aDateTime, + const String& aUser, + const String& aComment ); + // only to be used in the XML import + ScChangeAction( ScChangeActionType, + const ScBigRange&, + const ULONG nAction); + + virtual ~ScChangeAction(); + + String GetRefString( const ScBigRange&, + ScDocument*, BOOL bFlag3D = FALSE ) const; + + void SetActionNumber( ULONG n ) { nAction = n; } + void SetRejectAction( ULONG n ) { nRejectAction = n; } + void SetUser( const String& r ) { aUser = r; } + void SetType( ScChangeActionType e ) { eType = e; } + void SetState( ScChangeActionState e ) { eState = e; } + void SetRejected(); + + ScBigRange& GetBigRange() { return aBigRange; } + + ScChangeActionLinkEntry* AddLink( ScChangeAction* p, + ScChangeActionLinkEntry* pL ) + { + ScChangeActionLinkEntry* pLnk = + new ScChangeActionLinkEntry( + &pLinkAny, p ); + pLnk->SetLink( pL ); + return pLnk; + } + void RemoveAllAnyLinks(); + + virtual ScChangeActionLinkEntry* GetDeletedIn() const + { return pLinkDeletedIn; } + virtual ScChangeActionLinkEntry** GetDeletedInAddress() + { return &pLinkDeletedIn; } + ScChangeActionLinkEntry* AddDeletedIn( ScChangeAction* p ) + { + return new ScChangeActionLinkEntry( + GetDeletedInAddress(), p ); + } + BOOL RemoveDeletedIn( const ScChangeAction* ); + void SetDeletedIn( ScChangeAction* ); + + ScChangeActionLinkEntry* AddDeleted( ScChangeAction* p ) + { + return new ScChangeActionLinkEntry( + &pLinkDeleted, p ); + } + void RemoveAllDeleted(); + + ScChangeActionLinkEntry* AddDependent( ScChangeAction* p ) + { + return new ScChangeActionLinkEntry( + &pLinkDependent, p ); + } + void RemoveAllDependent(); + + void RemoveAllLinks(); + + virtual void AddContent( ScChangeActionContent* ) = 0; + virtual void DeleteCellEntries() = 0; + + virtual void UpdateReference( const ScChangeTrack*, + UpdateRefMode, const ScBigRange&, + INT32 nDx, INT32 nDy, INT32 nDz ); + + void Accept(); + virtual BOOL Reject( ScDocument* ) = 0; + void RejectRestoreContents( ScChangeTrack*, + SCsCOL nDx, SCsROW nDy ); + + // used in Reject() instead of IsRejectable() + BOOL IsInternalRejectable() const; + + // Derived classes that hold a pointer to the + // ChangeTrack must return that. Otherwise NULL. + virtual const ScChangeTrack* GetChangeTrack() const = 0; + +public: + + BOOL IsInsertType() const + { + return eType == SC_CAT_INSERT_COLS || + eType == SC_CAT_INSERT_ROWS || + eType == SC_CAT_INSERT_TABS; + } + BOOL IsDeleteType() const + { + return eType == SC_CAT_DELETE_COLS || + eType == SC_CAT_DELETE_ROWS || + eType == SC_CAT_DELETE_TABS; + } + BOOL IsVirgin() const + { return eState == SC_CAS_VIRGIN; } + BOOL IsAccepted() const + { return eState == SC_CAS_ACCEPTED; } + BOOL IsRejected() const + { return eState == SC_CAS_REJECTED; } + + // Action rejects another Action + BOOL IsRejecting() const + { return nRejectAction != 0; } + + // ob Action im Dokument sichtbar ist + BOOL IsVisible() const; + + // ob Action anfassbar ist + BOOL IsTouchable() const; + + // ob Action ein Eintrag in Dialog-Root ist + BOOL IsDialogRoot() const; + + // ob ein Eintrag im Dialog aufklappbar sein soll + BOOL IsDialogParent() const; + + // ob Action ein Delete ist, unter dem + // aufgeklappt mehrere einzelne Deletes sind + BOOL IsMasterDelete() const; + + // ob Action akzeptiert/selektiert/abgelehnt + // werden kann + BOOL IsClickable() const; + + // ob Action abgelehnt werden kann + BOOL IsRejectable() const; + + const ScBigRange& GetBigRange() const { return aBigRange; } + SC_DLLPUBLIC DateTime GetDateTime() const; // local time + const DateTime& GetDateTimeUTC() const // UTC time + { return aDateTime; } + const String& GetUser() const { return aUser; } + const String& GetComment() const { return aComment; } + ScChangeActionType GetType() const { return eType; } + ScChangeActionState GetState() const { return eState; } + ULONG GetActionNumber() const { return nAction; } + ULONG GetRejectAction() const { return nRejectAction; } + + ScChangeAction* GetNext() const { return pNext; } + ScChangeAction* GetPrev() const { return pPrev; } + + BOOL IsDeletedIn() const + { return GetDeletedIn() != NULL; } + BOOL IsDeleted() const + { return IsDeleteType() || IsDeletedIn(); } + BOOL IsDeletedIn( const ScChangeAction* ) const; + BOOL IsDeletedInDelType( ScChangeActionType ) const; + void RemoveAllDeletedIn(); + + const ScChangeActionLinkEntry* GetFirstDeletedEntry() const + { return pLinkDeleted; } + const ScChangeActionLinkEntry* GetFirstDependentEntry() const + { return pLinkDependent; } + BOOL HasDependent() const + { return pLinkDependent != NULL; } + BOOL HasDeleted() const + { return pLinkDeleted != NULL; } + + // Description wird an String angehaengt. + // Mit bSplitRange wird bei Delete nur + // eine Spalte/Zeile beruecksichtigt (fuer + // Auflistung der einzelnen Eintraege). + virtual void GetDescription( String&, ScDocument*, + BOOL bSplitRange = FALSE, bool bWarning = true ) const; + + virtual void GetRefString( String&, ScDocument*, + BOOL bFlag3D = FALSE ) const; + + // fuer DocumentMerge altes Datum einer anderen + // Action setzen, mit GetDateTimeUTC geholt + void SetDateTimeUTC( const DateTime& rDT ) + { aDateTime = rDT; } + + // Benutzerkommentar setzen + void SetComment( const String& rStr ) + { aComment = rStr; } + + // only to be used in the XML import + void SetDeletedInThis( ULONG nActionNumber, + const ScChangeTrack* pTrack ); + // only to be used in the XML import + void AddDependent( ULONG nActionNumber, + const ScChangeTrack* pTrack ); +#if DEBUG_CHANGETRACK + String ToString( ScDocument* pDoc ) const; +#endif // DEBUG_CHANGETRACK +}; + + +// --- ScChangeActionIns ---------------------------------------------------- + +class ScChangeActionIns : public ScChangeAction +{ + friend class ScChangeTrack; + + ScChangeActionIns( const ScRange& rRange ); + virtual ~ScChangeActionIns(); + + virtual void AddContent( ScChangeActionContent* ) {} + virtual void DeleteCellEntries() {} + + virtual BOOL Reject( ScDocument* ); + + virtual const ScChangeTrack* GetChangeTrack() const { return 0; } + +public: + ScChangeActionIns(const ULONG nActionNumber, + const ScChangeActionState eState, + const ULONG nRejectingNumber, + const ScBigRange& aBigRange, + const String& aUser, + const DateTime& aDateTime, + const String &sComment, + const ScChangeActionType eType); // only to use in the XML import + + virtual void GetDescription( String&, ScDocument*, + BOOL bSplitRange = FALSE, bool bWarning = true ) const; +}; + + +// --- ScChangeActionDel ---------------------------------------------------- + +class ScChangeActionMove; + +class ScChangeActionDelMoveEntry : public ScChangeActionLinkEntry +{ + friend class ScChangeActionDel; + friend class ScChangeTrack; + + short nCutOffFrom; + short nCutOffTo; + + + ScChangeActionDelMoveEntry( + ScChangeActionDelMoveEntry** ppPrevP, + ScChangeActionMove* pMove, + short nFrom, short nTo ) + : ScChangeActionLinkEntry( + (ScChangeActionLinkEntry**) + ppPrevP, + (ScChangeAction*) pMove ), + nCutOffFrom( nFrom ), + nCutOffTo( nTo ) + {} + + ScChangeActionDelMoveEntry* GetNext() + { + return (ScChangeActionDelMoveEntry*) + ScChangeActionLinkEntry::GetNext(); + } + ScChangeActionMove* GetMove() + { + return (ScChangeActionMove*) + ScChangeActionLinkEntry::GetAction(); + } + +public: + const ScChangeActionDelMoveEntry* GetNext() const + { + return (const ScChangeActionDelMoveEntry*) + ScChangeActionLinkEntry::GetNext(); + } + const ScChangeActionMove* GetMove() const + { + return (const ScChangeActionMove*) + ScChangeActionLinkEntry::GetAction(); + } + short GetCutOffFrom() const { return nCutOffFrom; } + short GetCutOffTo() const { return nCutOffTo; } +}; + + +class ScChangeActionDel : public ScChangeAction +{ + friend class ScChangeTrack; + friend void ScChangeAction::Accept(); + + ScChangeTrack* pTrack; + ScChangeActionCellListEntry* pFirstCell; + ScChangeActionIns* pCutOff; // abgeschnittener Insert + short nCutOff; // +: Start -: End + ScChangeActionDelMoveEntry* pLinkMove; + SCsCOL nDx; + SCsROW nDy; + + ScChangeActionDel( const ScRange& rRange, + SCsCOL nDx, SCsROW nDy, ScChangeTrack* ); + virtual ~ScChangeActionDel(); + + ScChangeActionIns* GetCutOffInsert() { return pCutOff; } + + virtual void AddContent( ScChangeActionContent* ); + virtual void DeleteCellEntries(); + + void UndoCutOffMoves(); + void UndoCutOffInsert(); + + virtual void UpdateReference( const ScChangeTrack*, + UpdateRefMode, const ScBigRange&, + INT32 nDx, INT32 nDy, INT32 nDz ); + + virtual BOOL Reject( ScDocument* ); + + virtual const ScChangeTrack* GetChangeTrack() const { return pTrack; } + +public: + ScChangeActionDel(const ULONG nActionNumber, + const ScChangeActionState eState, + const ULONG nRejectingNumber, + const ScBigRange& aBigRange, + const String& aUser, + const DateTime& aDateTime, + const String &sComment, + const ScChangeActionType eType, + const SCsCOLROW nD, + ScChangeTrack* pTrack); // only to use in the XML import + // wich of nDx and nDy is set is depend on the type + + // ob dieses das unterste einer Reihe (oder + // auch einzeln) ist + BOOL IsBaseDelete() const; + + // ob dieses das oberste einer Reihe (oder + // auch einzeln) ist + BOOL IsTopDelete() const; + + // ob dieses ein Teil einer Reihe ist + BOOL IsMultiDelete() const; + + // ob es eine Col ist, die zu einem TabDelete gehoert + BOOL IsTabDeleteCol() const; + + SCsCOL GetDx() const { return nDx; } + SCsROW GetDy() const { return nDy; } + ScBigRange GetOverAllRange() const; // BigRange + (nDx, nDy) + + const ScChangeActionCellListEntry* GetFirstCellEntry() const + { return pFirstCell; } + const ScChangeActionDelMoveEntry* GetFirstMoveEntry() const + { return pLinkMove; } + const ScChangeActionIns* GetCutOffInsert() const { return pCutOff; } + short GetCutOffCount() const { return nCutOff; } + + virtual void GetDescription( String&, ScDocument*, + BOOL bSplitRange = FALSE, bool bWarning = true ) const; + void SetCutOffInsert( ScChangeActionIns* p, short n ) + { pCutOff = p; nCutOff = n; } // only to use in the XML import + // this should be protected, but for the XML import it is public + // only to use in the XML import + // this should be protected, but for the XML import it is public + ScChangeActionDelMoveEntry* AddCutOffMove( ScChangeActionMove* pMove, + short nFrom, short nTo ) + { + return new ScChangeActionDelMoveEntry( + &pLinkMove, pMove, nFrom, nTo ); + } +}; + + +// --- ScChangeActionMove --------------------------------------------------- + +class ScChangeActionMove : public ScChangeAction +{ + friend class ScChangeTrack; + friend class ScChangeActionDel; + + ScBigRange aFromRange; + ScChangeTrack* pTrack; + ScChangeActionCellListEntry* pFirstCell; + ULONG nStartLastCut; // fuer PasteCut Undo + ULONG nEndLastCut; + + ScChangeActionMove( const ScRange& rFromRange, + const ScRange& rToRange, + ScChangeTrack* pTrackP ) + : ScChangeAction( SC_CAT_MOVE, rToRange ), + aFromRange( rFromRange ), + pTrack( pTrackP ), + pFirstCell( NULL ), + nStartLastCut(0), + nEndLastCut(0) + {} + virtual ~ScChangeActionMove(); + + virtual void AddContent( ScChangeActionContent* ); + virtual void DeleteCellEntries(); + + ScBigRange& GetFromRange() { return aFromRange; } + + void SetStartLastCut( ULONG nVal ) { nStartLastCut = nVal; } + ULONG GetStartLastCut() const { return nStartLastCut; } + void SetEndLastCut( ULONG nVal ) { nEndLastCut = nVal; } + ULONG GetEndLastCut() const { return nEndLastCut; } + + virtual void UpdateReference( const ScChangeTrack*, + UpdateRefMode, const ScBigRange&, + INT32 nDx, INT32 nDy, INT32 nDz ); + + virtual BOOL Reject( ScDocument* ); + + virtual const ScChangeTrack* GetChangeTrack() const { return pTrack; } + +protected: + using ScChangeAction::GetRefString; + +public: + ScChangeActionMove(const ULONG nActionNumber, + const ScChangeActionState eState, + const ULONG nRejectingNumber, + const ScBigRange& aToBigRange, + const String& aUser, + const DateTime& aDateTime, + const String &sComment, + const ScBigRange& aFromBigRange, + ScChangeTrack* pTrack); // only to use in the XML import + const ScChangeActionCellListEntry* GetFirstCellEntry() const + { return pFirstCell; } // only to use in the XML export + + const ScBigRange& GetFromRange() const { return aFromRange; } + SC_DLLPUBLIC void GetDelta( INT32& nDx, INT32& nDy, INT32& nDz ) const; + + virtual void GetDescription( String&, ScDocument*, + BOOL bSplitRange = FALSE, bool bWarning = true ) const; + + virtual void GetRefString( String&, ScDocument*, + BOOL bFlag3D = FALSE ) const; +}; + + +// --- ScChangeActionContent ------------------------------------------------ + +enum ScChangeActionContentCellType +{ + SC_CACCT_NONE = 0, + SC_CACCT_NORMAL, + SC_CACCT_MATORG, + SC_CACCT_MATREF +}; + +class Stack; + +class ScChangeActionContent : public ScChangeAction +{ + friend class ScChangeTrack; + + String aOldValue; + String aNewValue; + ScBaseCell* pOldCell; + ScBaseCell* pNewCell; + ScChangeActionContent* pNextContent; // an gleicher Position + ScChangeActionContent* pPrevContent; + ScChangeActionContent* pNextInSlot; // in gleichem Slot + ScChangeActionContent** ppPrevInSlot; + + void InsertInSlot( ScChangeActionContent** pp ) + { + if ( !ppPrevInSlot ) + { + ppPrevInSlot = pp; + if ( ( pNextInSlot = *pp ) != NULL ) + pNextInSlot->ppPrevInSlot = &pNextInSlot; + *pp = this; + } + } + void RemoveFromSlot() + { + if ( ppPrevInSlot ) + { + if ( ( *ppPrevInSlot = pNextInSlot ) != NULL ) + pNextInSlot->ppPrevInSlot = ppPrevInSlot; + ppPrevInSlot = NULL; // not inserted + } + } + ScChangeActionContent* GetNextInSlot() { return pNextInSlot; } + + void ClearTrack(); + + static void GetStringOfCell( String& rStr, + const ScBaseCell* pCell, + const ScDocument* pDoc, + const ScAddress& rPos ); + + static void GetStringOfCell( String& rStr, + const ScBaseCell* pCell, + const ScDocument* pDoc, + ULONG nFormat ); + + static void SetValue( String& rStr, ScBaseCell*& pCell, + const ScAddress& rPos, + const ScBaseCell* pOrgCell, + const ScDocument* pFromDoc, + ScDocument* pToDoc ); + + static void SetValue( String& rStr, ScBaseCell*& pCell, + ULONG nFormat, + const ScBaseCell* pOrgCell, + const ScDocument* pFromDoc, + ScDocument* pToDoc ); + + static void SetCell( String& rStr, ScBaseCell* pCell, + ULONG nFormat, const ScDocument* pDoc ); + + static BOOL NeedsNumberFormat( const ScBaseCell* ); + + void SetValueString( String& rValue, + ScBaseCell*& pCell, const String& rStr, + ScDocument* pDoc ); + + void GetValueString( String& rStr, + const String& rValue, + const ScBaseCell* pCell ) const; + + void GetFormulaString( String& rStr, + const ScFormulaCell* pCell ) const; + + virtual void AddContent( ScChangeActionContent* ) {} + virtual void DeleteCellEntries() {} + + virtual void UpdateReference( const ScChangeTrack*, + UpdateRefMode, const ScBigRange&, + INT32 nDx, INT32 nDy, INT32 nDz ); + + virtual BOOL Reject( ScDocument* ); + + virtual const ScChangeTrack* GetChangeTrack() const { return 0; } + + // pRejectActions!=NULL: reject actions get + // stacked, no SetNewValue, no Append + BOOL Select( ScDocument*, ScChangeTrack*, + BOOL bOldest, Stack* pRejectActions ); + + void PutValueToDoc( ScBaseCell*, const String&, + ScDocument*, SCsCOL nDx, SCsROW nDy ) const; + +protected: + using ScChangeAction::GetRefString; + +public: + + DECL_FIXEDMEMPOOL_NEWDEL( ScChangeActionContent ) + + ScChangeActionContent( const ScRange& rRange ) + : ScChangeAction( SC_CAT_CONTENT, rRange ), + pOldCell( NULL ), + pNewCell( NULL ), + pNextContent( NULL ), + pPrevContent( NULL ), + pNextInSlot( NULL ), + ppPrevInSlot( NULL ) + {} + ScChangeActionContent(const ULONG nActionNumber, + const ScChangeActionState eState, + const ULONG nRejectingNumber, + const ScBigRange& aBigRange, + const String& aUser, + const DateTime& aDateTime, + const String &sComment, + ScBaseCell* pOldCell, + ScDocument* pDoc, + const String& sOldValue); // to use for XML Import + ScChangeActionContent(const ULONG nActionNumber, + ScBaseCell* pNewCell, + const ScBigRange& aBigRange, + ScDocument* pDoc, + const String& sNewValue); // to use for XML Import of Generated Actions + virtual ~ScChangeActionContent(); + + ScChangeActionContent* GetNextContent() const { return pNextContent; } + ScChangeActionContent* GetPrevContent() const { return pPrevContent; } + ScChangeActionContent* GetTopContent() const; + BOOL IsTopContent() const + { return pNextContent == NULL; } + + virtual ScChangeActionLinkEntry* GetDeletedIn() const; + virtual ScChangeActionLinkEntry** GetDeletedInAddress(); + + void PutOldValueToDoc( ScDocument*, + SCsCOL nDx, SCsROW nDy ) const; + void PutNewValueToDoc( ScDocument*, + SCsCOL nDx, SCsROW nDy ) const; + + void SetOldValue( const ScBaseCell*, + const ScDocument* pFromDoc, + ScDocument* pToDoc, + ULONG nFormat ); + void SetOldValue( const ScBaseCell*, + const ScDocument* pFromDoc, + ScDocument* pToDoc ); + void SetNewValue( const ScBaseCell*, ScDocument* ); + + // Used in import filter AppendContentOnTheFly, + // takes ownership of cells. + void SetOldNewCells( ScBaseCell* pOldCell, + ULONG nOldFormat, ScBaseCell* pNewCell, + ULONG nNewFormat, ScDocument* pDoc ); + + // Use this only in the XML import, + // takes ownership of cell. + void SetNewCell( ScBaseCell* pCell, ScDocument* pDoc, const String& rFormatted ); + + // These functions should be protected but for + // the XML import they are public. + void SetNextContent( ScChangeActionContent* p ) + { pNextContent = p; } + void SetPrevContent( ScChangeActionContent* p ) + { pPrevContent = p; } + + // moeglichst nicht verwenden, + // setzt nur String bzw. generiert Formelzelle + void SetOldValue( const String& rOld, ScDocument* ); + void SetNewValue( const String& rNew, ScDocument* ); + + void GetOldString( String& ) const; + void GetNewString( String& ) const; + const ScBaseCell* GetOldCell() const { return pOldCell; } + const ScBaseCell* GetNewCell() const { return pNewCell; } + virtual void GetDescription( String&, ScDocument*, + BOOL bSplitRange = FALSE, bool bWarning = true ) const; + virtual void GetRefString( String&, ScDocument*, + BOOL bFlag3D = FALSE ) const; + + static ScChangeActionContentCellType GetContentCellType( const ScBaseCell* ); + + // NewCell + BOOL IsMatrixOrigin() const + { + return GetContentCellType( GetNewCell() ) + == SC_CACCT_MATORG; + } + BOOL IsMatrixReference() const + { + return GetContentCellType( GetNewCell() ) + == SC_CACCT_MATREF; + } + // OldCell + BOOL IsOldMatrixOrigin() const + { + return GetContentCellType( GetOldCell() ) + == SC_CACCT_MATORG; + } + BOOL IsOldMatrixReference() const + { + return GetContentCellType( GetOldCell() ) + == SC_CACCT_MATREF; + } + +}; + + +// --- ScChangeActionReject ------------------------------------------------- + +class Stack; + +class ScChangeActionReject : public ScChangeAction +{ + friend class ScChangeTrack; + friend class ScChangeActionContent; + + ScChangeActionReject( ULONG nReject ) + : ScChangeAction( SC_CAT_REJECT, ScRange() ) + { + SetRejectAction( nReject ); + SetState( SC_CAS_ACCEPTED ); + } + + virtual void AddContent( ScChangeActionContent* ) {} + virtual void DeleteCellEntries() {} + + virtual BOOL Reject( ScDocument* ) { return FALSE; } + + virtual const ScChangeTrack* GetChangeTrack() const { return 0; } + +public: + ScChangeActionReject(const ULONG nActionNumber, + const ScChangeActionState eState, + const ULONG nRejectingNumber, + const ScBigRange& aBigRange, + const String& aUser, + const DateTime& aDateTime, + const String &sComment); // only to use in the XML import +}; + + +// --- ScChangeTrack -------------------------------------------------------- + +enum ScChangeTrackMsgType +{ + SC_CTM_NONE, + SC_CTM_APPEND, // Actions angehaengt + SC_CTM_REMOVE, // Actions weggenommen + SC_CTM_CHANGE, // Actions geaendert + SC_CTM_PARENT // war kein Parent und ist jetzt einer +}; + +struct ScChangeTrackMsgInfo +{ + DECL_FIXEDMEMPOOL_NEWDEL( ScChangeTrackMsgInfo ) + + ScChangeTrackMsgType eMsgType; + ULONG nStartAction; + ULONG nEndAction; +}; + +// MsgQueue fuer Benachrichtigung via ModifiedLink +DECLARE_QUEUE( ScChangeTrackMsgQueue, ScChangeTrackMsgInfo* ) +DECLARE_STACK( ScChangeTrackMsgStack, ScChangeTrackMsgInfo* ) + +enum ScChangeTrackMergeState +{ + SC_CTMS_NONE, + SC_CTMS_PREPARE, + SC_CTMS_OWN, + SC_CTMS_UNDO, + SC_CTMS_OTHER +}; + +// zusaetzlich zu pFirst/pNext/pLast/pPrev eine Table, um schnell sowohl +// per ActionNumber als auch ueber Liste zugreifen zu koennen +DECLARE_TABLE( ScChangeActionTable, ScChangeAction* ) + +// Intern generierte Actions beginnen bei diesem Wert (fast alle Bits gesetzt) +// und werden runtergezaehlt, um sich in einer Table wertemaessig nicht mit den +// "normalen" Actions in die Quere zu kommen. +#define SC_CHGTRACK_GENERATED_START ((UINT32) 0xfffffff0) + +class ScChangeTrack : public utl::ConfigurationListener +{ + friend void ScChangeAction::RejectRestoreContents( ScChangeTrack*, SCsCOL, SCsROW ); + friend BOOL ScChangeActionDel::Reject( ScDocument* pDoc ); + friend void ScChangeActionDel::DeleteCellEntries(); + friend void ScChangeActionMove::DeleteCellEntries(); + friend BOOL ScChangeActionMove::Reject( ScDocument* pDoc ); + + static const SCROW nContentRowsPerSlot; + static const SCSIZE nContentSlots; + + com::sun::star::uno::Sequence< sal_Int8 > aProtectPass; + ScChangeActionTable aTable; + ScChangeActionTable aGeneratedTable; + ScChangeActionTable aPasteCutTable; + ScChangeTrackMsgQueue aMsgQueue; + ScChangeTrackMsgStack aMsgStackTmp; + ScChangeTrackMsgStack aMsgStackFinal; + ScStrCollection aUserCollection; + String aUser; + Link aModifiedLink; + ScRange aInDeleteRange; + DateTime aFixDateTime; + ScChangeAction* pFirst; + ScChangeAction* pLast; + ScChangeActionContent* pFirstGeneratedDelContent; + ScChangeActionContent** ppContentSlots; + ScChangeActionMove* pLastCutMove; + ScChangeActionLinkEntry* pLinkInsertCol; + ScChangeActionLinkEntry* pLinkInsertRow; + ScChangeActionLinkEntry* pLinkInsertTab; + ScChangeActionLinkEntry* pLinkMove; + ScChangeTrackMsgInfo* pBlockModifyMsg; + ScDocument* pDoc; + ULONG nActionMax; + ULONG nGeneratedMin; + ULONG nMarkLastSaved; + ULONG nStartLastCut; + ULONG nEndLastCut; + ULONG nLastMerge; + ScChangeTrackMergeState eMergeState; + USHORT nLoadedFileFormatVersion; + BOOL bLoadSave; + BOOL bInDelete; + BOOL bInDeleteUndo; + BOOL bInDeleteTop; + BOOL bInPasteCut; + BOOL bUseFixDateTime; + BOOL bTime100thSeconds; + + // not implemented, prevent usage + ScChangeTrack( const ScChangeTrack& ); + ScChangeTrack& operator=( const ScChangeTrack& ); + +#ifdef SC_CHGTRACK_CXX + static SCROW InitContentRowsPerSlot(); + + // TRUE if one is MM_FORMULA and the other is + // not, or if both are and range differs + static BOOL IsMatrixFormulaRangeDifferent( + const ScBaseCell* pOldCell, + const ScBaseCell* pNewCell ); + + void Init(); + void DtorClear(); + void SetLoadSave( BOOL bVal ) { bLoadSave = bVal; } + void SetInDeleteRange( const ScRange& rRange ) + { aInDeleteRange = rRange; } + void SetInDelete( BOOL bVal ) + { bInDelete = bVal; } + void SetInDeleteTop( BOOL bVal ) + { bInDeleteTop = bVal; } + void SetInDeleteUndo( BOOL bVal ) + { bInDeleteUndo = bVal; } + void SetInPasteCut( BOOL bVal ) + { bInPasteCut = bVal; } + void SetMergeState( ScChangeTrackMergeState eState ) + { eMergeState = eState; } + ScChangeTrackMergeState GetMergeState() const { return eMergeState; } + void SetLastMerge( ULONG nVal ) { nLastMerge = nVal; } + ULONG GetLastMerge() const { return nLastMerge; } + + void SetLastCutMoveRange( const ScRange&, ScDocument* ); + + // ModifyMsg blockweise und nicht einzeln erzeugen + void StartBlockModify( ScChangeTrackMsgType, + ULONG nStartAction ); + void EndBlockModify( ULONG nEndAction ); + + void AddDependentWithNotify( ScChangeAction* pParent, + ScChangeAction* pDependent ); + + void Dependencies( ScChangeAction* ); + void UpdateReference( ScChangeAction*, BOOL bUndo ); + void UpdateReference( ScChangeAction** ppFirstAction, + ScChangeAction* pAct, BOOL bUndo ); + void Append( ScChangeAction* pAppend, ULONG nAction ); + SC_DLLPUBLIC void AppendDeleteRange( const ScRange&, + ScDocument* pRefDoc, SCsTAB nDz, + ULONG nRejectingInsert ); + void AppendOneDeleteRange( const ScRange& rOrgRange, + ScDocument* pRefDoc, + SCsCOL nDx, SCsROW nDy, SCsTAB nDz, + ULONG nRejectingInsert ); + void LookUpContents( const ScRange& rOrgRange, + ScDocument* pRefDoc, + SCsCOL nDx, SCsROW nDy, SCsTAB nDz ); + void Remove( ScChangeAction* ); + void MasterLinks( ScChangeAction* ); + + // Content on top an Position + ScChangeActionContent* SearchContentAt( const ScBigAddress&, + ScChangeAction* pButNotThis ) const; + void DeleteGeneratedDelContent( + ScChangeActionContent* ); + ScChangeActionContent* GenerateDelContent( const ScAddress&, + const ScBaseCell*, + const ScDocument* pFromDoc ); + void DeleteCellEntries( + ScChangeActionCellListEntry*&, + ScChangeAction* pDeletor ); + + // Action und alle abhaengigen rejecten, + // Table stammt aus vorherigem GetDependents, + // ist nur bei Insert und Move (MasterType) + // noetig, kann ansonsten NULL sein. + // bRecursion == Aufruf aus Reject mit Table + BOOL Reject( ScChangeAction*, + ScChangeActionTable*, BOOL bRecursion ); + +#endif // SC_CHGTRACK_CXX + + void ClearMsgQueue(); + virtual void ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 ); + +public: + + static SCSIZE ComputeContentSlot( INT32 nRow ) + { + if ( nRow < 0 || nRow > MAXROW ) + return nContentSlots - 1; + return static_cast< SCSIZE >( nRow / nContentRowsPerSlot ); + } + + SC_DLLPUBLIC ScChangeTrack( ScDocument* ); + ScChangeTrack( ScDocument*, + const ScStrCollection& ); // only to use in the XML import + SC_DLLPUBLIC virtual ~ScChangeTrack(); + void Clear(); + + ScChangeActionContent* GetFirstGenerated() const { return pFirstGeneratedDelContent; } + ScChangeAction* GetFirst() const { return pFirst; } + ScChangeAction* GetLast() const { return pLast; } + ULONG GetActionMax() const { return nActionMax; } + BOOL IsGenerated( ULONG nAction ) const + { return nAction >= nGeneratedMin; } + ScChangeAction* GetAction( ULONG nAction ) const + { return aTable.Get( nAction ); } + ScChangeAction* GetGenerated( ULONG nGenerated ) const + { return aGeneratedTable.Get( nGenerated ); } + ScChangeAction* GetActionOrGenerated( ULONG nAction ) const + { + return IsGenerated( nAction ) ? + GetGenerated( nAction ) : + GetAction( nAction ); + } + ULONG GetLastSavedActionNumber() const + { return nMarkLastSaved; } + void SetLastSavedActionNumber(ULONG nNew) + { nMarkLastSaved = nNew; } + ScChangeAction* GetLastSaved() const + { return aTable.Get( nMarkLastSaved ); } + ScChangeActionContent** GetContentSlots() const { return ppContentSlots; } + + BOOL IsLoadSave() const { return bLoadSave; } + const ScRange& GetInDeleteRange() const + { return aInDeleteRange; } + BOOL IsInDelete() const { return bInDelete; } + BOOL IsInDeleteTop() const { return bInDeleteTop; } + BOOL IsInDeleteUndo() const { return bInDeleteUndo; } + BOOL IsInPasteCut() const { return bInPasteCut; } + SC_DLLPUBLIC void SetUser( const String& ); + const String& GetUser() const { return aUser; } + const ScStrCollection& GetUserCollection() const + { return aUserCollection; } + ScDocument* GetDocument() const { return pDoc; } + // for import filter + const DateTime& GetFixDateTime() const { return aFixDateTime; } + + // set this if the date/time set with + // SetFixDateTime...() shall be applied to + // appended actions + void SetUseFixDateTime( BOOL bVal ) + { bUseFixDateTime = bVal; } + // for MergeDocument, apply original date/time as UTC + void SetFixDateTimeUTC( const DateTime& rDT ) + { aFixDateTime = rDT; } + // for import filter, apply original date/time as local time + void SetFixDateTimeLocal( const DateTime& rDT ) + { aFixDateTime = rDT; aFixDateTime.ConvertToUTC(); } + + void Append( ScChangeAction* ); + + // pRefDoc may be NULL => no lookup of contents + // => no generation of deleted contents + SC_DLLPUBLIC void AppendDeleteRange( const ScRange&, + ScDocument* pRefDoc, + ULONG& nStartAction, ULONG& nEndAction, + SCsTAB nDz = 0 ); + // nDz: Multi-TabDel, LookUpContent ist + // um -nDz verschoben zu suchen + + // nachdem neuer Wert im Dokument gesetzt wurde, + // alter Wert aus RefDoc/UndoDoc + void AppendContent( const ScAddress& rPos, + ScDocument* pRefDoc ); + // nachdem neue Werte im Dokument gesetzt wurden, + // alte Werte aus RefDoc/UndoDoc + void AppendContentRange( const ScRange& rRange, + ScDocument* pRefDoc, + ULONG& nStartAction, ULONG& nEndAction, + ScChangeActionClipMode eMode = SC_CACM_NONE ); + // nachdem neuer Wert im Dokument gesetzt wurde, + // alter Wert aus pOldCell, nOldFormat, + // RefDoc==NULL => Doc + void AppendContent( const ScAddress& rPos, + const ScBaseCell* pOldCell, + ULONG nOldFormat, ScDocument* pRefDoc = NULL ); + // nachdem neuer Wert im Dokument gesetzt wurde, + // alter Wert aus pOldCell, Format aus Doc + void AppendContent( const ScAddress& rPos, + const ScBaseCell* pOldCell ); + // nachdem neue Werte im Dokument gesetzt wurden, + // alte Werte aus RefDoc/UndoDoc. + // Alle Contents, wo im RefDoc eine Zelle steht. + void AppendContentsIfInRefDoc( ScDocument* pRefDoc, + ULONG& nStartAction, ULONG& nEndAction ); + + // Meant for import filter, creates and inserts + // an unconditional content action of the two + // cells without querying the document, not + // even for number formats (though the number + // formatter of the document may be used). + // The action is returned and may be used to + // set user name, description, date/time et al. + // Takes ownership of the cells! + SC_DLLPUBLIC ScChangeActionContent* AppendContentOnTheFly( const ScAddress& rPos, + ScBaseCell* pOldCell, + ScBaseCell* pNewCell, + ULONG nOldFormat = 0, + ULONG nNewFormat = 0 ); + + // die folgenden beiden nur benutzen wenn's + // nicht anders geht (setzen nur String fuer + // NewValue bzw. Formelerzeugung) + + // bevor neuer Wert im Dokument gesetzt wird + void AppendContent( const ScAddress& rPos, + const String& rNewValue, + ScBaseCell* pOldCell ); + + SC_DLLPUBLIC void AppendInsert( const ScRange& ); + + // pRefDoc may be NULL => no lookup of contents + // => no generation of deleted contents + SC_DLLPUBLIC void AppendMove( const ScRange& rFromRange, + const ScRange& rToRange, + ScDocument* pRefDoc ); + + // Cut to Clipboard + void ResetLastCut() + { + nStartLastCut = nEndLastCut = 0; + if ( pLastCutMove ) + { + delete pLastCutMove; + pLastCutMove = NULL; + } + } + BOOL HasLastCut() const + { + return nEndLastCut > 0 && + nStartLastCut <= nEndLastCut && + pLastCutMove; + } + + SC_DLLPUBLIC void Undo( ULONG nStartAction, ULONG nEndAction, bool bMerge = false ); + + // fuer MergeDocument, Referenzen anpassen, + //! darf nur in einem temporaer geoeffneten + //! Dokument verwendet werden, der Track + //! ist danach verhunzt + void MergePrepare( ScChangeAction* pFirstMerge, bool bShared = false ); + void MergeOwn( ScChangeAction* pAct, ULONG nFirstMerge, bool bShared = false ); + static BOOL MergeIgnore( const ScChangeAction&, ULONG nFirstMerge ); + + // Abhaengige in Table einfuegen. + // Bei Insert sind es echte Abhaengige, + // bei Move abhaengige Contents im FromRange + // und geloeschte im ToRange bzw. Inserts in + // FromRange oder ToRange, + // bei Delete eine Liste der geloeschten, + // bei Content andere Contents an gleicher + // Position oder MatrixReferences zu MatrixOrigin. + // Mit bListMasterDelete werden unter einem + // MasterDelete alle zu diesem Delete gehoerenden + // Deletes einer Reihe gelistet. + // Mit bAllFlat werden auch alle Abhaengigen + // der Abhaengigen flach eingefuegt. + SC_DLLPUBLIC void GetDependents( ScChangeAction*, + ScChangeActionTable&, + BOOL bListMasterDelete = FALSE, + BOOL bAllFlat = FALSE ) const; + + // Reject visible Action (und abhaengige) + BOOL Reject( ScChangeAction*, bool bShared = false ); + + // Accept visible Action (und abhaengige) + SC_DLLPUBLIC BOOL Accept( ScChangeAction* ); + + void AcceptAll(); // alle Virgins + BOOL RejectAll(); // alle Virgins + + // Selektiert einen Content von mehreren an + // gleicher Position und akzeptiert diesen und + // die aelteren, rejected die neueren. + // Mit bOldest==TRUE wird der erste OldValue + // einer Virgin-Content-Kette restauriert. + BOOL SelectContent( ScChangeAction*, + BOOL bOldest = FALSE ); + + // wenn ModifiedLink gesetzt, landen + // Aenderungen in ScChangeTrackMsgQueue + void SetModifiedLink( const Link& r ) + { aModifiedLink = r; ClearMsgQueue(); } + const Link& GetModifiedLink() const { return aModifiedLink; } + ScChangeTrackMsgQueue& GetMsgQueue() { return aMsgQueue; } + + void NotifyModified( ScChangeTrackMsgType eMsgType, + ULONG nStartAction, ULONG nEndAction ); + + USHORT GetLoadedFileFormatVersion() const + { return nLoadedFileFormatVersion; } + + ULONG AddLoadedGenerated(ScBaseCell* pOldCell, + const ScBigRange& aBigRange, const String& sNewValue ); // only to use in the XML import + void AppendLoaded( ScChangeAction* pAppend ); // this is only for the XML import public, it should be protected + void SetActionMax(ULONG nTempActionMax) + { nActionMax = nTempActionMax; } // only to use in the XML import + + void SetProtection( const com::sun::star::uno::Sequence< sal_Int8 >& rPass ) + { aProtectPass = rPass; } + com::sun::star::uno::Sequence< sal_Int8 > GetProtection() const + { return aProtectPass; } + BOOL IsProtected() const + { return aProtectPass.getLength() != 0; } + + // If time stamps of actions of this + // ChangeTrack and a second one are to be + // compared including 100th seconds. + void SetTime100thSeconds( BOOL bVal ) + { bTime100thSeconds = bVal; } + BOOL IsTime100thSeconds() const + { return bTime100thSeconds; } + + void AppendCloned( ScChangeAction* pAppend ); + SC_DLLPUBLIC ScChangeTrack* Clone( ScDocument* pDocument ) const; + void MergeActionState( ScChangeAction* pAct, const ScChangeAction* pOtherAct ); +#if DEBUG_CHANGETRACK + String ToString() const; +#endif // DEBUG_CHANGETRACK +}; + + +#endif + + |