/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* 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 .
*/
#pragma once
#include <memory>
#include <stack>
#include <tools/datetime.hxx>
#include <unotools/securityoptions.hxx>
#include <chgtrack.hxx>
#include <document.hxx>
#include "xelink.hxx"
#include "xestring.hxx"
#include "excrecds.hxx"
#include "xlformula.hxx"
#include "xllink.hxx"
#include "xeformula.hxx"
class ExcXmlRecord : public ExcRecord
{
public:
virtual std::size_t GetLen() const override;
virtual sal_uInt16 GetNum() const override;
virtual void Save( XclExpStream& rStrm ) override;
};
// XclExpUserBView - one UserBView record for each user
class XclExpUserBView : public ExcRecord
{
private:
XclExpString sUsername;
sal_uInt8 aGUID[ 16 ];
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
XclExpUserBView( const OUString& rUsername, const sal_uInt8* pGUID );
const sal_uInt8* GetGUID() const { return aGUID; }
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// XclExpUserBViewList - list of UserBView records
class XclExpUserBViewList : public ExcEmptyRec
{
private:
std::vector<XclExpUserBView> aViews;
public:
typedef std::vector<XclExpUserBView>::const_iterator const_iterator;
XclExpUserBViewList( const ScChangeTrack& rChangeTrack );
virtual ~XclExpUserBViewList() override;
const_iterator cbegin () { return aViews.cbegin(); }
const_iterator cend () { return aViews.cend(); }
virtual void Save( XclExpStream& rStrm ) override;
};
// XclExpUsersViewBegin - begin of view block (one per sheet)
class XclExpUsersViewBegin : public ExcRecord
{
private:
sal_uInt8 aGUID[ 16 ];
sal_uInt32 nCurrTab;
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
XclExpUsersViewBegin( const sal_uInt8* pGUID, sal_uInt32 nTab );
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// XclExpUsersViewEnd - end of view block (one per sheet)
class XclExpUsersViewEnd : public ExcRecord
{
private:
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// dummy record for "User Names" stream
class XclExpChTr0x0191 : public ExcRecord
{
private:
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// dummy record for "User Names" stream
class XclExpChTr0x0198 : public ExcRecord
{
private:
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// dummy record for "User Names" stream
class XclExpChTr0x0192 : public ExcRecord
{
private:
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// dummy record for "User Names" stream
class XclExpChTr0x0197 : public ExcRecord
{
private:
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// dummy record without content
class XclExpChTrEmpty : public ExcRecord
{
private:
sal_uInt16 nRecNum;
public:
XclExpChTrEmpty( sal_uInt16 nNum ) : nRecNum( nNum ) {}
virtual ~XclExpChTrEmpty() override;
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// dummy record for "Revision Log" stream
class XclExpChTr0x0195 : public ExcRecord
{
private:
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
virtual ~XclExpChTr0x0195() override;
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// dummy record for "Revision Log" stream
class XclExpChTr0x0194 : public ExcRecord
{
private:
XclExpString sUsername;
DateTime aDateTime;
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
inline XclExpChTr0x0194( const ScChangeTrack& rChangeTrack );
virtual ~XclExpChTr0x0194() override;
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
inline XclExpChTr0x0194::XclExpChTr0x0194( const ScChangeTrack& rChangeTrack ) :
sUsername( rChangeTrack.GetUser() ),
aDateTime( rChangeTrack.GetFixDateTime() )
{
}
// XclExpChTrHeader - header record, includes action count
class XclExpChTrHeader : public ExcRecord
{
private:
sal_uInt8 aGUID[ 16 ];
sal_uInt32 nCount;
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
XclExpChTrHeader() : nCount( 0 ) {}
virtual ~XclExpChTrHeader() override;
void SetGUID( const sal_uInt8* pGUID ) { memcpy( aGUID, pGUID, 16 ); }
void SetCount( sal_uInt32 nNew ) { nCount = nNew; }
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
virtual void SaveXml( XclExpXmlStream& rStrm ) override;
};
class XclExpXmlChTrHeaders : public ExcXmlRecord
{
sal_uInt8 maGUID[16];
public:
void SetGUID( const sal_uInt8* pGUID );
virtual void SaveXml( XclExpXmlStream& rStrm ) override;
};
class XclExpChTrTabIdBuffer;
class XclExpChTrAction;
class XclExpXmlChTrHeader : public ExcXmlRecord
{
OUString maUserName;
DateTime maDateTime;
sal_uInt8 maGUID[16];
sal_Int32 mnLogNumber;
sal_uInt32 mnMinAction;
sal_uInt32 mnMaxAction;
std::vector<sal_uInt16> maTabBuffer;
std::vector<std::unique_ptr<XclExpChTrAction>> maActions;
public:
XclExpXmlChTrHeader(
OUString aUserName, const DateTime& rDateTime, const sal_uInt8* pGUID,
sal_Int32 nLogNumber, const XclExpChTrTabIdBuffer& rBuf );
virtual void SaveXml( XclExpXmlStream& rStrm ) override;
void AppendAction( std::unique_ptr<XclExpChTrAction> pAction );
private:
/// map authors to remove personal info
std::unique_ptr<SvtSecurityMapPersonalInfo> mpAuthorIDs;
};
// XclExpChTrInfo - header of action group of a user
class XclExpChTrInfo : public ExcRecord
{
private:
XclExpString sUsername;
DateTime aDateTime;
sal_uInt8 aGUID[ 16 ];
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
XclExpChTrInfo( const OUString& rUsername, const DateTime& rDateTime,
const sal_uInt8* pGUID );
virtual ~XclExpChTrInfo() override;
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// XclExpChTrTabIdBuffer - buffer for tab id's
class XclExpChTrTabIdBuffer
{
private:
std::unique_ptr<sal_uInt16[]>
pBuffer;
sal_uInt16* pLast;
sal_uInt16 nBufSize;
sal_uInt16 nLastId;
public:
XclExpChTrTabIdBuffer( sal_uInt16 nCount );
XclExpChTrTabIdBuffer( const XclExpChTrTabIdBuffer& rCopy );
~XclExpChTrTabIdBuffer();
void InitFill( sal_uInt16 nIndex );
void InitFillup();
sal_uInt16 GetId( sal_uInt16 nIndex ) const;
bool HasId( sal_uInt16 nIndex ) const;
void Remove();
sal_uInt16 GetBufferCount() const
{ return static_cast< sal_uInt16 >( (pLast - pBuffer.get()) + 1 ); }
void GetBufferCopy( sal_uInt16* pDest ) const
{ memcpy( pDest, pBuffer.get(), sizeof(sal_uInt16) * GetBufferCount() ); }
};
// XclExpChTrTabId - tab id record
class XclExpChTrTabId : public ExcRecord
{
private:
std::unique_ptr<sal_uInt16[]> pBuffer;
sal_uInt16 nTabCount;
void Clear() { pBuffer.reset(); }
virtual void SaveCont( XclExpStream& rStrm ) override;
public:
XclExpChTrTabId( sal_uInt16 nCount ) : nTabCount( nCount ) {}
XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer );
virtual ~XclExpChTrTabId() override;
void Copy( const XclExpChTrTabIdBuffer& rBuffer );
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetLen() const override;
};
// XclExpChTrAction - base class for action records
class XclExpChTrAction : public ExcRecord
{
private:
OUString sUsername;
DateTime aDateTime;
sal_uInt32 nIndex; // action number
std::unique_ptr<XclExpChTrAction>
pAddAction; // additional record for this action
bool bAccepted;
protected:
const XclExpTabInfo& rTabInfo; // for table num export (sc num -> xcl num)
const XclExpChTrTabIdBuffer& rIdBuffer; // for table num export (xcl num -> tab id)
sal_uInt32 nLength; // this is not the record size
sal_uInt16 nOpCode; // EXC_CHTR_OP_***
bool bForceInfo;
XclExpChTrAction( const XclExpChTrAction& rCopy );
void SetAddAction( XclExpChTrAction* pAction );
void AddDependentContents(
const ScChangeAction& rAction,
const XclExpRoot& rRoot,
const ScChangeTrack& rChangeTrack );
static inline void Write2DAddress( XclExpStream& rStrm, const ScAddress& rAddress );
static inline void Write2DRange( XclExpStream& rStrm, const ScRange& rRange );
inline sal_uInt16 GetTabId( SCTAB nTabId ) const;
inline bool IsDeletedTab( SCTAB nTab ) const;
inline void WriteTabId( XclExpStream& rStrm, SCTAB nTabId ) const;
// save header data, call SaveActionData()
virtual void SaveCont( XclExpStream& rStrm ) override;
static std::size_t GetHeaderByteCount() { return 12; }
// override to save action data without header, called by SaveCont()
virtual void SaveActionData( XclExpStream& rStrm ) const = 0;
// override to get action size without header, called by GetLen()
virtual std::size_t GetActionByteCount() const = 0;
// true if export would attempt to get the tab id of an unknown tab
virtual bool UsesDeletedTab() const = 0;
// do something before writing the record
virtual void PrepareSaveAction( XclExpStream& rStrm ) const;
// do something after writing the record
virtual void CompleteSaveAction( XclExpStream& rStrm ) const;
bool GetAccepted() const { return bAccepted; }
public:
XclExpChTrAction(
const ScChangeAction& rAction,
const XclExpRoot& rRoot,
const XclExpChTrTabIdBuffer& rTabIdBuffer,
sal_uInt16 nNewOpCode = EXC_CHTR_OP_UNKNOWN );
virtual ~XclExpChTrAction() override;
const OUString& GetUsername() const { return sUsername; }
const DateTime& GetDateTime() const { return aDateTime; }
const XclExpChTrTabIdBuffer& GetTabIdBuffer() const { return rIdBuffer; }
bool ForceInfoRecord() const { return bForceInfo; }
// set own index & return new index
// could override to use more indexes per action
void SetIndex( sal_uInt32& rIndex );
virtual void Save( XclExpStream& rStrm ) override;
virtual std::size_t GetLen() const override;
XclExpChTrAction* GetAddAction() { return pAddAction.get(); }
sal_uInt32 GetActionNumber() const { return nIndex; }
};
inline void XclExpChTrAction::Write2DAddress( XclExpStream& rStrm, const ScAddress& rAddress )
{
rStrm << static_cast<sal_uInt16>(rAddress.Row())
<< static_cast<sal_uInt16>(rAddress.Col());
}
inline void XclExpChTrAction::Write2DRange( XclExpStream& rStrm, const ScRange& rRange )
{
rStrm << static_cast<sal_uInt16>(rRange.aStart.Row())
<< static_cast<sal_uInt16>(rRange.aEnd.Row())
<< static_cast<sal_uInt16>(rRange.aStart.Col())
<< static_cast<sal_uInt16>(rRange.aEnd.Col());
}
inline bool XclExpChTrAction::IsDeletedTab(SCTAB nTab) const
{
return rTabInfo.GetXclTab(nTab) == EXC_TAB_DELETED;
}
inline sal_uInt16 XclExpChTrAction::GetTabId( SCTAB nTab ) const
{
return rIdBuffer.GetId( rTabInfo.GetXclTab( nTab ) );
}
inline void XclExpChTrAction::WriteTabId( XclExpStream& rStrm, SCTAB nTab ) const
{
rStrm << GetTabId( nTab );
}
// XclExpChTrData - cell content itself
struct XclExpChTrData
{
std::unique_ptr<XclExpString> pString;
XclExpStringRef mpFormattedString;
const ScFormulaCell* mpFormulaCell;
XclTokenArrayRef mxTokArr;
XclExpRefLog maRefLog;
double fValue;
sal_Int32 nRKValue;
sal_uInt16 nType;
std::size_t nSize;
XclExpChTrData();
~XclExpChTrData();
void Clear();
void WriteFormula(
XclExpStream& rStrm,
const XclExpChTrTabIdBuffer& rTabIdBuffer );
void Write(
XclExpStream& rStrm,
const XclExpChTrTabIdBuffer& rTabIdBuffer );
bool UsesDeletedTab(const XclExpChTrTabIdBuffer& rTabIdBuffer) const;
};
// XclExpChTrCellContent - changed cell content
class XclExpChTrCellContent final : public XclExpChTrAction, protected XclExpRoot
{
std::unique_ptr<XclExpChTrData> pOldData;
std::unique_ptr<XclExpChTrData> pNewData;
sal_uInt16 nOldLength; // this is not the record size
ScAddress aPosition;
static void MakeEmptyChTrData( std::unique_ptr<XclExpChTrData>& rpData );
void GetCellData(
const XclExpRoot& rRoot, const ScCellValue& rScCell, std::unique_ptr<XclExpChTrData>& rpData,
sal_uInt32& rXclLength1, sal_uInt16& rXclLength2 );
virtual bool UsesDeletedTab() const override;
virtual void SaveActionData( XclExpStream& rStrm ) const override;
public:
XclExpChTrCellContent(
const ScChangeActionContent& rAction,
const XclExpRoot& rRoot,
const XclExpChTrTabIdBuffer& rTabIdBuffer );
virtual ~XclExpChTrCellContent() override;
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetActionByteCount() const override;
virtual void SaveXml( XclExpXmlStream& rStrm ) override;
};
// XclExpChTrInsert - insert/delete columns/rows
class XclExpChTrInsert : public XclExpChTrAction
{
bool mbEndOfList;
protected:
ScRange aRange;
XclExpChTrInsert( const XclExpChTrInsert& rCopy );
virtual bool UsesDeletedTab() const override;
virtual void SaveActionData( XclExpStream& rStrm ) const override;
virtual void PrepareSaveAction( XclExpStream& rStrm ) const override;
virtual void CompleteSaveAction( XclExpStream& rStrm ) const override;
public:
XclExpChTrInsert(
const ScChangeAction& rAction,
const XclExpRoot& rRoot,
const XclExpChTrTabIdBuffer& rTabIdBuffer,
const ScChangeTrack& rChangeTrack );
virtual ~XclExpChTrInsert() override;
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetActionByteCount() const override;
virtual void SaveXml( XclExpXmlStream& rStrm ) override;
};
// XclExpChTrInsertTab - insert table
class XclExpChTrInsertTab : public XclExpChTrAction, protected XclExpRoot
{
private:
SCTAB nTab;
protected:
virtual bool UsesDeletedTab() const override;
virtual void SaveActionData( XclExpStream& rStrm ) const override;
public:
XclExpChTrInsertTab(
const ScChangeAction& rAction,
const XclExpRoot& rRoot,
const XclExpChTrTabIdBuffer& rTabIdBuffer );
virtual ~XclExpChTrInsertTab() override;
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetActionByteCount() const override;
virtual void SaveXml( XclExpXmlStream& rStrm ) override;
};
// XclExpChTrMoveRange - move cell range
class XclExpChTrMoveRange final : public XclExpChTrAction
{
ScRange aSourceRange;
ScRange aDestRange;
virtual bool UsesDeletedTab() const override;
virtual void SaveActionData( XclExpStream& rStrm ) const override;
virtual void PrepareSaveAction( XclExpStream& rStrm ) const override;
virtual void CompleteSaveAction( XclExpStream& rStrm ) const override;
public:
XclExpChTrMoveRange(
const ScChangeActionMove& rAction,
const XclExpRoot& rRoot,
const XclExpChTrTabIdBuffer& rTabIdBuffer,
const ScChangeTrack& rChangeTrack );
virtual ~XclExpChTrMoveRange() override;
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetActionByteCount() const override;
virtual void SaveXml( XclExpXmlStream& rStrm ) override;
};
// XclExpChTr0x019A - additional data for delete action
class XclExpChTr0x014A : public XclExpChTrInsert
{
protected:
virtual void SaveActionData( XclExpStream& rStrm ) const override;
public:
XclExpChTr0x014A( const XclExpChTrInsert& rAction );
virtual ~XclExpChTr0x014A() override;
virtual sal_uInt16 GetNum() const override;
virtual std::size_t GetActionByteCount() const override;
virtual void SaveXml( XclExpXmlStream& rStrm ) override;
};
// XclExpChangeTrack - exports the "Revision Log" stream
class XclExpChangeTrack : protected XclExpRoot
{
typedef std::vector<std::unique_ptr<ExcRecord>> RecListType;
RecListType maRecList; // list of "Revision Log" stream records
std::stack<XclExpChTrAction*> aActionStack;
XclExpChTrTabIdBuffer* pTabIdBuffer;
std::vector<std::unique_ptr<XclExpChTrTabIdBuffer>>
maBuffers;
ScDocumentUniquePtr xTempDoc; // empty document
ScChangeTrack* CreateTempChangeTrack();
void PushActionRecord( const ScChangeAction& rAction );
bool WriteUserNamesStream();
public:
XclExpChangeTrack( const XclExpRoot& rRoot );
virtual ~XclExpChangeTrack() override;
void Write();
void WriteXml( XclExpXmlStream& rStrm );
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V690 The 'XclExpChTrTabIdBuffer' class implements a copy constructor, but lacks the copy assignment operator. It is dangerous to use such a class.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: aGUID.