| /************************************************************** |
| * |
| * 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 <sot/storage.hxx> |
| #include "XclExpChangeTrack.hxx" |
| #include "xeformula.hxx" |
| #include "cell.hxx" |
| #include "xcl97rec.hxx" |
| |
| //___________________________________________________________________ |
| // local functions |
| |
| void lcl_WriteDateTime( XclExpStream& rStrm, const DateTime& rDateTime ) |
| { |
| rStrm.SetSliceSize( 7 ); |
| rStrm << (sal_uInt16) rDateTime.GetYear() |
| << (sal_uInt8) rDateTime.GetMonth() |
| << (sal_uInt8) rDateTime.GetDay() |
| << (sal_uInt8) rDateTime.GetHour() |
| << (sal_uInt8) rDateTime.GetMin() |
| << (sal_uInt8) rDateTime.GetSec(); |
| rStrm.SetSliceSize( 0 ); |
| } |
| |
| // write string and fill rest of <nLength> with zero bytes |
| // <nLength> is without string header |
| void lcl_WriteFixedString( XclExpStream& rStrm, const XclExpString& rString, sal_Size nLength ) |
| { |
| sal_Size nStrBytes = rString.GetBufferSize(); |
| DBG_ASSERT( nLength >= nStrBytes, "lcl_WriteFixedString - String too long" ); |
| if( rString.Len() > 0 ) |
| rStrm << rString; |
| if( nLength > nStrBytes ) |
| rStrm.WriteZeroBytes( nLength - nStrBytes ); |
| } |
| |
| inline void lcl_GenerateGUID( sal_uInt8* pGUID, sal_Bool& rValidGUID ) |
| { |
| rtl_createUuid( pGUID, rValidGUID ? pGUID : NULL, sal_False ); |
| rValidGUID = sal_True; |
| } |
| |
| inline void lcl_WriteGUID( XclExpStream& rStrm, const sal_uInt8* pGUID ) |
| { |
| rStrm.SetSliceSize( 16 ); |
| for( sal_Size nIndex = 0; nIndex < 16; nIndex++ ) |
| rStrm << pGUID[ nIndex ]; |
| rStrm.SetSliceSize( 0 ); |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpUserBView::XclExpUserBView( const String& rUsername, const sal_uInt8* pGUID ) : |
| sUsername( rUsername ) |
| { |
| memcpy( aGUID, pGUID, 16 ); |
| } |
| |
| void XclExpUserBView::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm << (sal_uInt32) 0xFF078014 |
| << (sal_uInt32) 0x00000001; |
| lcl_WriteGUID( rStrm, aGUID ); |
| rStrm.WriteZeroBytes( 8 ); |
| rStrm << (sal_uInt32) 1200 |
| << (sal_uInt32) 1000 |
| << (sal_uInt16) 1000 |
| << (sal_uInt16) 0x0CF7 |
| << (sal_uInt16) 0x0000 |
| << (sal_uInt16) 0x0001 |
| << (sal_uInt16) 0x0000; |
| if( sUsername.Len() > 0 ) |
| rStrm << sUsername; |
| } |
| |
| sal_uInt16 XclExpUserBView::GetNum() const |
| { |
| return 0x01A9; |
| } |
| |
| sal_Size XclExpUserBView::GetLen() const |
| { |
| return 50 + ((sUsername.Len() > 0) ? sUsername.GetSize() : 0); |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpUserBViewList::XclExpUserBViewList( const ScChangeTrack& rChangeTrack ) |
| { |
| sal_uInt8 aGUID[ 16 ]; |
| sal_Bool bValidGUID = sal_False; |
| const ScStrCollection& rStrColl = rChangeTrack.GetUserCollection(); |
| for( sal_uInt16 nIndex = 0; nIndex < rStrColl.GetCount(); nIndex++ ) |
| { |
| const StrData* pStrData = (const StrData*) rStrColl.At( nIndex ); |
| lcl_GenerateGUID( aGUID, bValidGUID ); |
| if( pStrData ) |
| List::Insert( new XclExpUserBView( pStrData->GetString(), aGUID ), LIST_APPEND ); |
| } |
| } |
| |
| XclExpUserBViewList::~XclExpUserBViewList() |
| { |
| for( XclExpUserBView* pRec = _First(); pRec; pRec = _Next() ) |
| delete pRec; |
| } |
| |
| void XclExpUserBViewList::Save( XclExpStream& rStrm ) |
| { |
| for( XclExpUserBView* pRec = _First(); pRec; pRec = _Next() ) |
| pRec->Save( rStrm ); |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpUsersViewBegin::XclExpUsersViewBegin( const sal_uInt8* pGUID, sal_uInt32 nTab ) : |
| nCurrTab( nTab ) |
| { |
| memcpy( aGUID, pGUID, 16 ); |
| } |
| |
| void XclExpUsersViewBegin::SaveCont( XclExpStream& rStrm ) |
| { |
| lcl_WriteGUID( rStrm, aGUID ); |
| rStrm << nCurrTab |
| << (sal_uInt32) 100 |
| << (sal_uInt32) 64 |
| << (sal_uInt32) 3 |
| << (sal_uInt32) 0x0000003C |
| << (sal_uInt16) 0 |
| << (sal_uInt16) 3 |
| << (sal_uInt16) 0 |
| << (sal_uInt16) 3 |
| << (double) 0 |
| << (double) 0 |
| << (sal_Int16) -1 |
| << (sal_Int16) -1; |
| } |
| |
| sal_uInt16 XclExpUsersViewBegin::GetNum() const |
| { |
| return 0x01AA; |
| } |
| |
| sal_Size XclExpUsersViewBegin::GetLen() const |
| { |
| return 64; |
| } |
| |
| //___________________________________________________________________ |
| |
| void XclExpUsersViewEnd::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm << (sal_uInt16) 0x0001; |
| } |
| |
| sal_uInt16 XclExpUsersViewEnd::GetNum() const |
| { |
| return 0x01AB; |
| } |
| |
| sal_Size XclExpUsersViewEnd::GetLen() const |
| { |
| return 2; |
| } |
| |
| //___________________________________________________________________ |
| |
| void XclExpChTr0x0191::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm << (sal_uInt16) 0x0000; |
| } |
| |
| sal_uInt16 XclExpChTr0x0191::GetNum() const |
| { |
| return 0x0191; |
| } |
| |
| sal_Size XclExpChTr0x0191::GetLen() const |
| { |
| return 2; |
| } |
| |
| //___________________________________________________________________ |
| |
| void XclExpChTr0x0198::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm << (sal_uInt16) 0x0006 |
| << (sal_uInt16) 0x0000; |
| } |
| |
| sal_uInt16 XclExpChTr0x0198::GetNum() const |
| { |
| return 0x0198; |
| } |
| |
| sal_Size XclExpChTr0x0198::GetLen() const |
| { |
| return 4; |
| } |
| |
| //___________________________________________________________________ |
| |
| void XclExpChTr0x0192::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm << sal_uInt16( 0x0022 ); |
| rStrm.WriteZeroBytes( 510 ); |
| } |
| |
| sal_uInt16 XclExpChTr0x0192::GetNum() const |
| { |
| return 0x0192; |
| } |
| |
| sal_Size XclExpChTr0x0192::GetLen() const |
| { |
| return 512; |
| } |
| |
| //___________________________________________________________________ |
| |
| void XclExpChTr0x0197::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm << (sal_uInt16) 0x0000; |
| } |
| |
| sal_uInt16 XclExpChTr0x0197::GetNum() const |
| { |
| return 0x0197; |
| } |
| |
| sal_Size XclExpChTr0x0197::GetLen() const |
| { |
| return 2; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrEmpty::~XclExpChTrEmpty() |
| { |
| } |
| |
| sal_uInt16 XclExpChTrEmpty::GetNum() const |
| { |
| return nRecNum; |
| } |
| |
| sal_Size XclExpChTrEmpty::GetLen() const |
| { |
| return 0; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTr0x0195::~XclExpChTr0x0195() |
| { |
| } |
| |
| void XclExpChTr0x0195::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm.WriteZeroBytes( 162 ); |
| } |
| |
| sal_uInt16 XclExpChTr0x0195::GetNum() const |
| { |
| return 0x0195; |
| } |
| |
| sal_Size XclExpChTr0x0195::GetLen() const |
| { |
| return 162; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTr0x0194::~XclExpChTr0x0194() |
| { |
| } |
| |
| void XclExpChTr0x0194::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm << (sal_uInt32) 0; |
| lcl_WriteDateTime( rStrm, aDateTime ); |
| rStrm << (sal_uInt8) 0; |
| lcl_WriteFixedString( rStrm, sUsername, 147 ); |
| } |
| |
| sal_uInt16 XclExpChTr0x0194::GetNum() const |
| { |
| return 0x0194; |
| } |
| |
| sal_Size XclExpChTr0x0194::GetLen() const |
| { |
| return 162; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrHeader::~XclExpChTrHeader() |
| { |
| } |
| |
| void XclExpChTrHeader::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm << (sal_uInt16) 0x0006 |
| << (sal_uInt16) 0x0000 |
| << (sal_uInt16) 0x000D; |
| lcl_WriteGUID( rStrm, aGUID ); |
| lcl_WriteGUID( rStrm, aGUID ); |
| rStrm << nCount |
| << (sal_uInt16) 0x0001 |
| << (sal_uInt32) 0x00000000 |
| << (sal_uInt16) 0x001E; |
| } |
| |
| sal_uInt16 XclExpChTrHeader::GetNum() const |
| { |
| return 0x0196; |
| } |
| |
| sal_Size XclExpChTrHeader::GetLen() const |
| { |
| return 50; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrInfo::~XclExpChTrInfo() |
| { |
| } |
| |
| void XclExpChTrInfo::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm << (sal_uInt32) 0xFFFFFFFF |
| << (sal_uInt32) 0x00000000 |
| << (sal_uInt32) 0x00000020 |
| << (sal_uInt16) 0xFFFF; |
| lcl_WriteGUID( rStrm, aGUID ); |
| rStrm << (sal_uInt16) 0x04B0; |
| lcl_WriteFixedString( rStrm, sUsername, 113 ); |
| lcl_WriteDateTime( rStrm, aDateTime ); |
| rStrm << (sal_uInt8) 0x0000 |
| << (sal_uInt16) 0x0002; |
| } |
| |
| sal_uInt16 XclExpChTrInfo::GetNum() const |
| { |
| return 0x0138; |
| } |
| |
| sal_Size XclExpChTrInfo::GetLen() const |
| { |
| return 158; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( sal_uInt16 nCount ) : |
| nBufSize( nCount ), |
| nLastId( nCount ) |
| { |
| pBuffer = new sal_uInt16[ nBufSize ]; |
| memset( pBuffer, 0, sizeof(sal_uInt16) * nBufSize ); |
| pLast = pBuffer + nBufSize - 1; |
| } |
| |
| XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( const XclExpChTrTabIdBuffer& rCopy ) : |
| nBufSize( rCopy.nBufSize ), |
| nLastId( rCopy.nLastId ) |
| { |
| pBuffer = new sal_uInt16[ nBufSize ]; |
| memcpy( pBuffer, rCopy.pBuffer, sizeof(sal_uInt16) * nBufSize ); |
| pLast = pBuffer + nBufSize - 1; |
| } |
| |
| XclExpChTrTabIdBuffer::~XclExpChTrTabIdBuffer() |
| { |
| delete[] pBuffer; |
| } |
| |
| void XclExpChTrTabIdBuffer::InitFill( sal_uInt16 nIndex ) |
| { |
| DBG_ASSERT( nIndex < nLastId, "XclExpChTrTabIdBuffer::Insert - out of range" ); |
| |
| sal_uInt16 nFreeCount = 0; |
| for( sal_uInt16* pElem = pBuffer; pElem <= pLast; pElem++ ) |
| { |
| if( !*pElem ) |
| nFreeCount++; |
| if( nFreeCount > nIndex ) |
| { |
| *pElem = nLastId--; |
| return; |
| } |
| } |
| } |
| |
| void XclExpChTrTabIdBuffer::InitFillup() |
| { |
| sal_uInt16 nFreeCount = 1; |
| for( sal_uInt16* pElem = pBuffer; pElem <= pLast; pElem++ ) |
| if( !*pElem ) |
| *pElem = nFreeCount++; |
| nLastId = nBufSize; |
| } |
| |
| sal_uInt16 XclExpChTrTabIdBuffer::GetId( sal_uInt16 nIndex ) const |
| { |
| DBG_ASSERT( nIndex < nBufSize, "XclExpChTrTabIdBuffer::GetId - out of range" ); |
| return pBuffer[ nIndex ]; |
| } |
| |
| void XclExpChTrTabIdBuffer::Remove() |
| { |
| DBG_ASSERT( pBuffer <= pLast, "XclExpChTrTabIdBuffer::Remove - buffer empty" ); |
| sal_uInt16* pElem = pBuffer; |
| while( (pElem <= pLast) && (*pElem != nLastId) ) |
| pElem++; |
| while( pElem < pLast ) |
| { |
| *pElem = *(pElem + 1); |
| pElem++; |
| } |
| pLast--; |
| nLastId--; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrTabIdBufferList::~XclExpChTrTabIdBufferList() |
| { |
| for( XclExpChTrTabIdBuffer* pBuffer = First(); pBuffer; pBuffer = Next() ) |
| delete pBuffer; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrTabId::XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer ) : |
| nTabCount( rBuffer.GetBufferCount() ) |
| { |
| pBuffer = new sal_uInt16[ nTabCount ]; |
| rBuffer.GetBufferCopy( pBuffer ); |
| } |
| |
| XclExpChTrTabId::~XclExpChTrTabId() |
| { |
| Clear(); |
| } |
| |
| void XclExpChTrTabId::Copy( const XclExpChTrTabIdBuffer& rBuffer ) |
| { |
| Clear(); |
| nTabCount = rBuffer.GetBufferCount(); |
| pBuffer = new sal_uInt16[ nTabCount ]; |
| rBuffer.GetBufferCopy( pBuffer ); |
| } |
| |
| void XclExpChTrTabId::SaveCont( XclExpStream& rStrm ) |
| { |
| rStrm.EnableEncryption(); |
| if( pBuffer ) |
| for( sal_uInt16* pElem = pBuffer; pElem < (pBuffer + nTabCount); pElem++ ) |
| rStrm << *pElem; |
| else |
| for( sal_uInt16 nIndex = 1; nIndex <= nTabCount; nIndex++ ) |
| rStrm << nIndex; |
| } |
| |
| sal_uInt16 XclExpChTrTabId::GetNum() const |
| { |
| return 0x013D; |
| } |
| |
| sal_Size XclExpChTrTabId::GetLen() const |
| { |
| return nTabCount << 1; |
| } |
| |
| //___________________________________________________________________ |
| |
| // ! does not copy additional actions |
| XclExpChTrAction::XclExpChTrAction( const XclExpChTrAction& rCopy ) : |
| ExcRecord( rCopy ), |
| sUsername( rCopy.sUsername ), |
| aDateTime( rCopy.aDateTime ), |
| nIndex( 0 ), |
| pAddAction( 0 ), |
| bAccepted( rCopy.bAccepted ), |
| rTabInfo( rCopy.rTabInfo ), |
| rIdBuffer( rCopy.rIdBuffer ), |
| nLength( rCopy.nLength ), |
| nOpCode( rCopy.nOpCode ), |
| bForceInfo( rCopy.bForceInfo ) |
| { |
| } |
| |
| XclExpChTrAction::XclExpChTrAction( |
| const ScChangeAction& rAction, |
| const XclExpRoot& rRoot, |
| const XclExpChTrTabIdBuffer& rTabIdBuffer, |
| sal_uInt16 nNewOpCode ) : |
| sUsername( rAction.GetUser() ), |
| aDateTime( rAction.GetDateTime() ), |
| nIndex( 0 ), |
| pAddAction( NULL ), |
| bAccepted( rAction.IsAccepted() ), |
| rTabInfo( rRoot.GetTabInfo() ), |
| rIdBuffer( rTabIdBuffer ), |
| nLength( 0 ), |
| nOpCode( nNewOpCode ), |
| bForceInfo( sal_False ) |
| { |
| aDateTime.SetSec( 0 ); |
| aDateTime.Set100Sec( 0 ); |
| } |
| |
| XclExpChTrAction::~XclExpChTrAction() |
| { |
| if( pAddAction ) |
| delete pAddAction; |
| } |
| |
| void XclExpChTrAction::SetAddAction( XclExpChTrAction* pAction ) |
| { |
| if( pAddAction ) |
| pAddAction->SetAddAction( pAction ); |
| else |
| pAddAction = pAction; |
| } |
| |
| void XclExpChTrAction::AddDependentContents( |
| const ScChangeAction& rAction, |
| const XclExpRoot& rRoot, |
| ScChangeTrack& rChangeTrack ) |
| { |
| ScChangeActionTable aActionTable; |
| rChangeTrack.GetDependents( (ScChangeAction*)(&rAction), aActionTable ); |
| for( const ScChangeAction* pDepAction = aActionTable.First(); pDepAction; pDepAction = aActionTable.Next() ) |
| if( pDepAction->GetType() == SC_CAT_CONTENT ) |
| SetAddAction( new XclExpChTrCellContent( |
| *((const ScChangeActionContent*) pDepAction), rRoot, rIdBuffer ) ); |
| } |
| |
| void XclExpChTrAction::SetIndex( sal_uInt32& rIndex ) |
| { |
| nIndex = rIndex++; |
| } |
| |
| void XclExpChTrAction::SaveCont( XclExpStream& rStrm ) |
| { |
| DBG_ASSERT( nOpCode != EXC_CHTR_OP_UNKNOWN, "XclExpChTrAction::SaveCont - unknown action" ); |
| rStrm << nLength |
| << nIndex |
| << nOpCode |
| << (sal_uInt16)(bAccepted ? EXC_CHTR_ACCEPT : EXC_CHTR_NOTHING); |
| SaveActionData( rStrm ); |
| } |
| |
| void XclExpChTrAction::PrepareSaveAction( XclExpStream& /*rStrm*/ ) const |
| { |
| } |
| |
| void XclExpChTrAction::CompleteSaveAction( XclExpStream& /*rStrm*/ ) const |
| { |
| } |
| |
| void XclExpChTrAction::Save( XclExpStream& rStrm ) |
| { |
| PrepareSaveAction( rStrm ); |
| ExcRecord::Save( rStrm ); |
| if( pAddAction ) |
| pAddAction->Save( rStrm ); |
| CompleteSaveAction( rStrm ); |
| } |
| |
| sal_Size XclExpChTrAction::GetLen() const |
| { |
| return GetHeaderByteCount() + GetActionByteCount(); |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrData::XclExpChTrData() : |
| pString( NULL ), |
| fValue( 0.0 ), |
| nRKValue( 0 ), |
| nType( EXC_CHTR_TYPE_EMPTY ), |
| nSize( 0 ) |
| { |
| } |
| |
| XclExpChTrData::~XclExpChTrData() |
| { |
| Clear(); |
| } |
| |
| void XclExpChTrData::Clear() |
| { |
| DELETEZ( pString ); |
| mxTokArr.reset(); |
| maRefLog.clear(); |
| fValue = 0.0; |
| nRKValue = 0; |
| nType = EXC_CHTR_TYPE_EMPTY; |
| nSize = 0; |
| } |
| |
| void XclExpChTrData::WriteFormula( XclExpStream& rStrm, const XclExpChTrTabIdBuffer& rTabIdBuffer ) |
| { |
| DBG_ASSERT( mxTokArr.is() && !mxTokArr->Empty(), "XclExpChTrData::Write - no formula" ); |
| rStrm << *mxTokArr; |
| |
| for( XclExpRefLog::const_iterator aIt = maRefLog.begin(), aEnd = maRefLog.end(); aIt != aEnd; ++aIt ) |
| { |
| if( aIt->mpUrl && aIt->mpFirstTab ) |
| { |
| rStrm << *aIt->mpUrl << (sal_uInt8) 0x01 << *aIt->mpFirstTab << (sal_uInt8) 0x02; |
| } |
| else |
| { |
| bool bSingleTab = aIt->mnFirstXclTab == aIt->mnLastXclTab; |
| rStrm.SetSliceSize( bSingleTab ? 6 : 8 ); |
| rStrm << (sal_uInt8) 0x01 << (sal_uInt8) 0x02 << (sal_uInt8) 0x00; |
| rStrm << rTabIdBuffer.GetId( aIt->mnFirstXclTab ); |
| if( bSingleTab ) |
| rStrm << (sal_uInt8) 0x02; |
| else |
| rStrm << (sal_uInt8) 0x00 << rTabIdBuffer.GetId( aIt->mnLastXclTab ); |
| } |
| } |
| rStrm.SetSliceSize( 0 ); |
| rStrm << (sal_uInt8) 0x00; |
| } |
| |
| void XclExpChTrData::Write( XclExpStream& rStrm, const XclExpChTrTabIdBuffer& rTabIdBuffer ) |
| { |
| switch( nType ) |
| { |
| case EXC_CHTR_TYPE_RK: |
| rStrm << nRKValue; |
| break; |
| case EXC_CHTR_TYPE_DOUBLE: |
| rStrm << fValue; |
| break; |
| case EXC_CHTR_TYPE_STRING: |
| DBG_ASSERT( pString, "XclExpChTrData::Write - no string" ); |
| rStrm << *pString; |
| break; |
| case EXC_CHTR_TYPE_FORMULA: |
| WriteFormula( rStrm, rTabIdBuffer ); |
| break; |
| } |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrCellContent::XclExpChTrCellContent( |
| const ScChangeActionContent& rAction, |
| const XclExpRoot& rRoot, |
| const XclExpChTrTabIdBuffer& rTabIdBuffer ) : |
| XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_CELL ), |
| XclExpRoot( rRoot ), |
| pOldData( 0 ), |
| pNewData( 0 ), |
| aPosition( rAction.GetBigRange().MakeRange().aStart ) |
| { |
| sal_uInt32 nDummy32; |
| sal_uInt16 nDummy16; |
| GetCellData( rAction.GetOldCell(), pOldData, nDummy32, nOldLength ); |
| GetCellData( rAction.GetNewCell(), pNewData, nLength, nDummy16 ); |
| } |
| |
| XclExpChTrCellContent::~XclExpChTrCellContent() |
| { |
| if( pOldData ) |
| delete pOldData; |
| if( pNewData ) |
| delete pNewData; |
| } |
| |
| void XclExpChTrCellContent::MakeEmptyChTrData( XclExpChTrData*& rpData ) |
| { |
| if( rpData ) |
| rpData->Clear(); |
| else |
| rpData = new XclExpChTrData; |
| } |
| |
| void XclExpChTrCellContent::GetCellData( |
| const ScBaseCell* pScCell, |
| XclExpChTrData*& rpData, |
| sal_uInt32& rXclLength1, |
| sal_uInt16& rXclLength2 ) |
| { |
| MakeEmptyChTrData( rpData ); |
| rXclLength1 = 0x0000003A; |
| rXclLength2 = 0x0000; |
| |
| if( !pScCell ) |
| { |
| delete rpData; |
| rpData = NULL; |
| return; |
| } |
| |
| switch( pScCell->GetCellType() ) |
| { |
| case CELLTYPE_VALUE: |
| { |
| rpData->fValue = ((const ScValueCell*) pScCell)->GetValue(); |
| if( XclTools::GetRKFromDouble( rpData->nRKValue, rpData->fValue ) ) |
| { |
| rpData->nType = EXC_CHTR_TYPE_RK; |
| rpData->nSize = 4; |
| rXclLength1 = 0x0000003E; |
| rXclLength2 = 0x0004; |
| } |
| else |
| { |
| rpData->nType = EXC_CHTR_TYPE_DOUBLE; |
| rpData->nSize = 8; |
| rXclLength1 = 0x00000042; |
| rXclLength2 = 0x0008; |
| } |
| } |
| break; |
| case CELLTYPE_STRING: |
| case CELLTYPE_EDIT: |
| { |
| String sCellStr; |
| if( pScCell->GetCellType() == CELLTYPE_STRING ) |
| ((const ScStringCell*) pScCell)->GetString( sCellStr ); |
| else |
| ((const ScEditCell*) pScCell)->GetString( sCellStr ); |
| rpData->pString = new XclExpString( sCellStr, EXC_STR_DEFAULT, 32766 ); |
| rpData->nType = EXC_CHTR_TYPE_STRING; |
| rpData->nSize = 3 + rpData->pString->GetSize(); |
| rXclLength1 = 64 + (sCellStr.Len() << 1); |
| rXclLength2 = 6 + (sal_uInt16)(sCellStr.Len() << 1); |
| } |
| break; |
| case CELLTYPE_FORMULA: |
| { |
| const ScFormulaCell* pFmlCell = (const ScFormulaCell*) pScCell; |
| const ScTokenArray* pTokenArray = pFmlCell->GetCode(); |
| if( pTokenArray ) |
| { |
| XclExpRefLog& rRefLog = rpData->maRefLog; |
| rpData->mxTokArr = GetFormulaCompiler().CreateFormula( |
| EXC_FMLATYPE_CELL, *pTokenArray, &pFmlCell->aPos, &rRefLog ); |
| rpData->nType = EXC_CHTR_TYPE_FORMULA; |
| sal_Size nSize = rpData->mxTokArr->GetSize() + 3; |
| |
| for( XclExpRefLog::const_iterator aIt = rRefLog.begin(), aEnd = rRefLog.end(); aIt != aEnd; ++aIt ) |
| { |
| if( aIt->mpUrl && aIt->mpFirstTab ) |
| nSize += aIt->mpUrl->GetSize() + aIt->mpFirstTab->GetSize() + 2; |
| else |
| nSize += (aIt->mnFirstXclTab == aIt->mnLastXclTab) ? 6 : 8; |
| } |
| rpData->nSize = ::std::min< sal_Size >( nSize, 0xFFFF ); |
| rXclLength1 = 0x00000052; |
| rXclLength2 = 0x0018; |
| } |
| } |
| break; |
| default:; |
| } |
| } |
| |
| void XclExpChTrCellContent::SaveActionData( XclExpStream& rStrm ) const |
| { |
| WriteTabId( rStrm, aPosition.Tab() ); |
| rStrm << (sal_uInt16)((pOldData ? (pOldData->nType << 3) : 0x0000) | (pNewData ? pNewData->nType : 0x0000)) |
| << (sal_uInt16) 0x0000; |
| Write2DAddress( rStrm, aPosition ); |
| rStrm << nOldLength |
| << (sal_uInt32) 0x00000000; |
| if( pOldData ) |
| pOldData->Write( rStrm, rIdBuffer ); |
| if( pNewData ) |
| pNewData->Write( rStrm, rIdBuffer ); |
| } |
| |
| sal_uInt16 XclExpChTrCellContent::GetNum() const |
| { |
| return 0x013B; |
| } |
| |
| sal_Size XclExpChTrCellContent::GetActionByteCount() const |
| { |
| sal_Size nLen = 16; |
| if( pOldData ) |
| nLen += pOldData->nSize; |
| if( pNewData ) |
| nLen += pNewData->nSize; |
| return nLen; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrInsert::XclExpChTrInsert( |
| const ScChangeAction& rAction, |
| const XclExpRoot& rRoot, |
| const XclExpChTrTabIdBuffer& rTabIdBuffer, |
| ScChangeTrack& rChangeTrack ) : |
| XclExpChTrAction( rAction, rRoot, rTabIdBuffer ), |
| aRange( rAction.GetBigRange().MakeRange() ) |
| { |
| nLength = 0x00000030; |
| switch( rAction.GetType() ) |
| { |
| case SC_CAT_INSERT_COLS: nOpCode = EXC_CHTR_OP_INSCOL; break; |
| case SC_CAT_INSERT_ROWS: nOpCode = EXC_CHTR_OP_INSROW; break; |
| case SC_CAT_DELETE_COLS: nOpCode = EXC_CHTR_OP_DELCOL; break; |
| case SC_CAT_DELETE_ROWS: nOpCode = EXC_CHTR_OP_DELROW; break; |
| default: |
| DBG_ERROR( "XclExpChTrInsert::XclExpChTrInsert - unknown action" ); |
| } |
| |
| if( nOpCode & EXC_CHTR_OP_COLFLAG ) |
| { |
| aRange.aStart.SetRow( 0 ); |
| aRange.aEnd.SetRow( rRoot.GetXclMaxPos().Row() ); |
| } |
| else |
| { |
| aRange.aStart.SetCol( 0 ); |
| aRange.aEnd.SetCol( rRoot.GetXclMaxPos().Col() ); |
| } |
| |
| if( nOpCode & EXC_CHTR_OP_DELFLAG ) |
| { |
| SetAddAction( new XclExpChTr0x014A( *this ) ); |
| AddDependentContents( rAction, rRoot, rChangeTrack ); |
| } |
| } |
| |
| XclExpChTrInsert::~XclExpChTrInsert() |
| { |
| } |
| |
| void XclExpChTrInsert::SaveActionData( XclExpStream& rStrm ) const |
| { |
| WriteTabId( rStrm, aRange.aStart.Tab() ); |
| rStrm << (sal_uInt16) 0x0000; |
| Write2DRange( rStrm, aRange ); |
| rStrm << (sal_uInt32) 0x00000000; |
| } |
| |
| void XclExpChTrInsert::PrepareSaveAction( XclExpStream& rStrm ) const |
| { |
| if( (nOpCode == EXC_CHTR_OP_DELROW) || (nOpCode == EXC_CHTR_OP_DELCOL) ) |
| XclExpChTrEmpty( 0x0150 ).Save( rStrm ); |
| } |
| |
| void XclExpChTrInsert::CompleteSaveAction( XclExpStream& rStrm ) const |
| { |
| if( (nOpCode == EXC_CHTR_OP_DELROW) || (nOpCode == EXC_CHTR_OP_DELCOL) ) |
| XclExpChTrEmpty( 0x0151 ).Save( rStrm ); |
| } |
| |
| sal_uInt16 XclExpChTrInsert::GetNum() const |
| { |
| return 0x0137; |
| } |
| |
| sal_Size XclExpChTrInsert::GetActionByteCount() const |
| { |
| return 16; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrInsertTab::XclExpChTrInsertTab( |
| const ScChangeAction& rAction, |
| const XclExpRoot& rRoot, |
| const XclExpChTrTabIdBuffer& rTabIdBuffer ) : |
| XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_INSTAB ), |
| XclExpRoot( rRoot ), |
| nTab( (SCTAB) rAction.GetBigRange().aStart.Tab() ) |
| { |
| nLength = 0x0000021C; |
| bForceInfo = sal_True; |
| } |
| |
| XclExpChTrInsertTab::~XclExpChTrInsertTab() |
| { |
| } |
| |
| void XclExpChTrInsertTab::SaveActionData( XclExpStream& rStrm ) const |
| { |
| WriteTabId( rStrm, nTab ); |
| rStrm << sal_uInt32( 0 ); |
| lcl_WriteFixedString( rStrm, XclExpString( GetTabInfo().GetScTabName( nTab ) ), 127 ); |
| lcl_WriteDateTime( rStrm, GetDateTime() ); |
| rStrm.WriteZeroBytes( 133 ); |
| } |
| |
| sal_uInt16 XclExpChTrInsertTab::GetNum() const |
| { |
| return 0x014D; |
| } |
| |
| sal_Size XclExpChTrInsertTab::GetActionByteCount() const |
| { |
| return 276; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrMoveRange::XclExpChTrMoveRange( |
| const ScChangeActionMove& rAction, |
| const XclExpRoot& rRoot, |
| const XclExpChTrTabIdBuffer& rTabIdBuffer, |
| ScChangeTrack& rChangeTrack ) : |
| XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_MOVE ), |
| aDestRange( rAction.GetBigRange().MakeRange() ) |
| { |
| nLength = 0x00000042; |
| aSourceRange = aDestRange; |
| sal_Int32 nDCols, nDRows, nDTabs; |
| rAction.GetDelta( nDCols, nDRows, nDTabs ); |
| aSourceRange.aStart.IncRow( (SCROW) -nDRows ); |
| aSourceRange.aStart.IncCol( (SCCOL) -nDCols ); |
| aSourceRange.aStart.IncTab( (SCTAB) -nDTabs ); |
| aSourceRange.aEnd.IncRow( (SCROW) -nDRows ); |
| aSourceRange.aEnd.IncCol( (SCCOL) -nDCols ); |
| aSourceRange.aEnd.IncTab( (SCTAB) -nDTabs ); |
| AddDependentContents( rAction, rRoot, rChangeTrack ); |
| } |
| |
| XclExpChTrMoveRange::~XclExpChTrMoveRange() |
| { |
| } |
| |
| void XclExpChTrMoveRange::SaveActionData( XclExpStream& rStrm ) const |
| { |
| WriteTabId( rStrm, aDestRange.aStart.Tab() ); |
| Write2DRange( rStrm, aSourceRange ); |
| Write2DRange( rStrm, aDestRange ); |
| WriteTabId( rStrm, aSourceRange.aStart.Tab() ); |
| rStrm << (sal_uInt32) 0x00000000; |
| } |
| |
| void XclExpChTrMoveRange::PrepareSaveAction( XclExpStream& rStrm ) const |
| { |
| XclExpChTrEmpty( 0x014E ).Save( rStrm ); |
| } |
| |
| void XclExpChTrMoveRange::CompleteSaveAction( XclExpStream& rStrm ) const |
| { |
| XclExpChTrEmpty( 0x014F ).Save( rStrm ); |
| } |
| |
| sal_uInt16 XclExpChTrMoveRange::GetNum() const |
| { |
| return 0x0140; |
| } |
| |
| sal_Size XclExpChTrMoveRange::GetActionByteCount() const |
| { |
| return 24; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTr0x014A::XclExpChTr0x014A( const XclExpChTrInsert& rAction ) : |
| XclExpChTrInsert( rAction ) |
| { |
| nLength = 0x00000026; |
| nOpCode = EXC_CHTR_OP_FORMAT; |
| } |
| |
| XclExpChTr0x014A::~XclExpChTr0x014A() |
| { |
| } |
| |
| void XclExpChTr0x014A::SaveActionData( XclExpStream& rStrm ) const |
| { |
| WriteTabId( rStrm, aRange.aStart.Tab() ); |
| rStrm << (sal_uInt16) 0x0003 |
| << (sal_uInt16) 0x0001; |
| Write2DRange( rStrm, aRange ); |
| } |
| |
| sal_uInt16 XclExpChTr0x014A::GetNum() const |
| { |
| return 0x014A; |
| } |
| |
| sal_Size XclExpChTr0x014A::GetActionByteCount() const |
| { |
| return 14; |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrActionStack::~XclExpChTrActionStack() |
| { |
| while( XclExpChTrAction* pRec = Pop() ) |
| delete pRec; |
| } |
| |
| void XclExpChTrActionStack::Push( XclExpChTrAction* pNewRec ) |
| { |
| DBG_ASSERT( pNewRec, "XclExpChTrActionStack::Push - NULL pointer" ); |
| if( pNewRec ) |
| Stack::Push( pNewRec ); |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChTrRecordList::~XclExpChTrRecordList() |
| { |
| for( ExcRecord* pRec = First(); pRec; pRec = Next() ) |
| delete pRec; |
| } |
| |
| void XclExpChTrRecordList::Append( ExcRecord* pNewRec ) |
| { |
| DBG_ASSERT( pNewRec, "XclExpChTrRecordList::Append - NULL pointer" ); |
| if( pNewRec ) |
| List::Insert( pNewRec, LIST_APPEND ); |
| } |
| |
| void XclExpChTrRecordList::Save( XclExpStream& rStrm ) |
| { |
| for( ExcRecord* pRec = First(); pRec; pRec = Next() ) |
| pRec->Save( rStrm ); |
| } |
| |
| //___________________________________________________________________ |
| |
| XclExpChangeTrack::XclExpChangeTrack( const XclExpRoot& rRoot ) : |
| XclExpRoot( rRoot ), |
| aRecList(), |
| aActionStack(), |
| aTabIdBufferList(), |
| pTabIdBuffer( NULL ), |
| pTempDoc( NULL ), |
| nNewAction( 1 ), |
| pHeader( NULL ), |
| bValidGUID( sal_False ) |
| { |
| DBG_ASSERT( GetOldRoot().pTabId, "XclExpChangeTrack::XclExpChangeTrack - root data incomplete" ); |
| if( !GetOldRoot().pTabId ) |
| return; |
| |
| ScChangeTrack* pTempChangeTrack = CreateTempChangeTrack(); |
| if (!pTempChangeTrack) |
| return; |
| |
| pTabIdBuffer = new XclExpChTrTabIdBuffer( GetTabInfo().GetXclTabCount() ); |
| aTabIdBufferList.Append( pTabIdBuffer ); |
| |
| // calculate final table order (tab id list) |
| const ScChangeAction* pScAction; |
| for( pScAction = pTempChangeTrack->GetLast(); pScAction; pScAction = pScAction->GetPrev() ) |
| { |
| if( pScAction->GetType() == SC_CAT_INSERT_TABS ) |
| { |
| SCTAB nScTab = static_cast< SCTAB >( pScAction->GetBigRange().aStart.Tab() ); |
| pTabIdBuffer->InitFill( GetTabInfo().GetXclTab( nScTab ) ); |
| } |
| } |
| pTabIdBuffer->InitFillup(); |
| GetOldRoot().pTabId->Copy( *pTabIdBuffer ); |
| |
| // get actions in reverse order |
| pScAction = pTempChangeTrack->GetLast(); |
| while( pScAction ) |
| { |
| PushActionRecord( *pScAction ); |
| const ScChangeAction* pPrevAction = pScAction->GetPrev(); |
| pTempChangeTrack->Undo( pScAction->GetActionNumber(), pScAction->GetActionNumber() ); |
| pScAction = pPrevAction; |
| } |
| |
| // build record list |
| pHeader = new XclExpChTrHeader; |
| aRecList.Append( pHeader ); |
| aRecList.Append( new XclExpChTr0x0195 ); |
| aRecList.Append( new XclExpChTr0x0194( *pTempChangeTrack ) ); |
| |
| String sLastUsername; |
| DateTime aLastDateTime; |
| sal_uInt32 nIndex = 1; |
| while( XclExpChTrAction* pAction = aActionStack.Pop() ) |
| { |
| if( (nIndex == 1) || pAction->ForceInfoRecord() || |
| (pAction->GetUsername() != sLastUsername) || |
| (pAction->GetDateTime() != aLastDateTime) ) |
| { |
| lcl_GenerateGUID( aGUID, bValidGUID ); |
| sLastUsername = pAction->GetUsername(); |
| aLastDateTime = pAction->GetDateTime(); |
| aRecList.Append( new XclExpChTrInfo( sLastUsername, aLastDateTime, aGUID ) ); |
| aRecList.Append( new XclExpChTrTabId( pAction->GetTabIdBuffer() ) ); |
| pHeader->SetGUID( aGUID ); |
| } |
| pAction->SetIndex( nIndex ); |
| aRecList.Append( pAction ); |
| } |
| |
| pHeader->SetGUID( aGUID ); |
| pHeader->SetCount( nIndex - 1 ); |
| aRecList.Append( new ExcEof ); |
| } |
| |
| XclExpChangeTrack::~XclExpChangeTrack() |
| { |
| if( pTempDoc ) |
| delete pTempDoc; |
| } |
| |
| ScChangeTrack* XclExpChangeTrack::CreateTempChangeTrack() |
| { |
| // get original change track |
| ScChangeTrack* pOrigChangeTrack = GetDoc().GetChangeTrack(); |
| DBG_ASSERT( pOrigChangeTrack, "XclExpChangeTrack::CreateTempChangeTrack - no change track data" ); |
| if( !pOrigChangeTrack ) |
| return NULL; |
| |
| // create empty document |
| pTempDoc = new ScDocument; |
| DBG_ASSERT( pTempDoc, "XclExpChangeTrack::CreateTempChangeTrack - no temp document" ); |
| if( !pTempDoc ) |
| return NULL; |
| |
| // adjust table count |
| SCTAB nOrigCount = GetDoc().GetTableCount(); |
| String sTabName; |
| for( sal_Int32 nIndex = 0; nIndex < nOrigCount; nIndex++ ) |
| { |
| pTempDoc->CreateValidTabName( sTabName ); |
| pTempDoc->InsertTab( SC_TAB_APPEND, sTabName ); |
| } |
| DBG_ASSERT( nOrigCount == pTempDoc->GetTableCount(), |
| "XclExpChangeTrack::CreateTempChangeTrack - table count mismatch" ); |
| if( nOrigCount != pTempDoc->GetTableCount() ) |
| return NULL; |
| |
| return pOrigChangeTrack->Clone(pTempDoc); |
| } |
| |
| void XclExpChangeTrack::PushActionRecord( const ScChangeAction& rAction ) |
| { |
| XclExpChTrAction* pXclAction = NULL; |
| ScChangeTrack* pTempChangeTrack = pTempDoc->GetChangeTrack(); |
| switch( rAction.GetType() ) |
| { |
| case SC_CAT_CONTENT: |
| pXclAction = new XclExpChTrCellContent( (const ScChangeActionContent&) rAction, GetRoot(), *pTabIdBuffer ); |
| break; |
| case SC_CAT_INSERT_ROWS: |
| case SC_CAT_INSERT_COLS: |
| case SC_CAT_DELETE_ROWS: |
| case SC_CAT_DELETE_COLS: |
| if (pTempChangeTrack) |
| pXclAction = new XclExpChTrInsert( rAction, GetRoot(), *pTabIdBuffer, *pTempChangeTrack ); |
| break; |
| case SC_CAT_INSERT_TABS: |
| { |
| pXclAction = new XclExpChTrInsertTab( rAction, GetRoot(), *pTabIdBuffer ); |
| XclExpChTrTabIdBuffer* pNewBuffer = new XclExpChTrTabIdBuffer( *pTabIdBuffer ); |
| pNewBuffer->Remove(); |
| aTabIdBufferList.Append( pNewBuffer ); |
| pTabIdBuffer = pNewBuffer; |
| } |
| break; |
| case SC_CAT_MOVE: |
| if (pTempChangeTrack) |
| pXclAction = new XclExpChTrMoveRange( (const ScChangeActionMove&) rAction, GetRoot(), *pTabIdBuffer, *pTempChangeTrack ); |
| break; |
| default:; |
| } |
| if( pXclAction ) |
| aActionStack.Push( pXclAction ); |
| } |
| |
| sal_Bool XclExpChangeTrack::WriteUserNamesStream() |
| { |
| sal_Bool bRet = sal_False; |
| SotStorageStreamRef xSvStrm = OpenStream( EXC_STREAM_USERNAMES ); |
| DBG_ASSERT( xSvStrm.Is(), "XclExpChangeTrack::WriteUserNamesStream - no stream" ); |
| if( xSvStrm.Is() ) |
| { |
| XclExpStream aXclStrm( *xSvStrm, GetRoot() ); |
| XclExpChTr0x0191().Save( aXclStrm ); |
| XclExpChTr0x0198().Save( aXclStrm ); |
| XclExpChTr0x0192().Save( aXclStrm ); |
| XclExpChTr0x0197().Save( aXclStrm ); |
| xSvStrm->Commit(); |
| bRet = sal_True; |
| } |
| return bRet; |
| } |
| |
| void XclExpChangeTrack::Write() |
| { |
| if( !aRecList.Count() ) |
| return; |
| |
| if( WriteUserNamesStream() ) |
| { |
| SotStorageStreamRef xSvStrm = OpenStream( EXC_STREAM_REVLOG ); |
| DBG_ASSERT( xSvStrm.Is(), "XclExpChangeTrack::Write - no stream" ); |
| if( xSvStrm.Is() ) |
| { |
| XclExpStream aXclStrm( *xSvStrm, GetRoot(), EXC_MAXRECSIZE_BIFF8 + 8 ); |
| aRecList.Save( aXclStrm ); |
| xSvStrm->Commit(); |
| } |
| } |
| } |
| |