update dev300-m58
[ooovba.git] / sc / source / filter / xcl97 / XclExpChangeTrack.cxx
blobefb224c2b7febdc9e6f7a6ef21dd0864c3fe4945
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: XclExpChangeTrack.cxx,v $
10 * $Revision: 1.26 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
35 //___________________________________________________________________
37 #include <sot/storage.hxx>
38 #include "XclExpChangeTrack.hxx"
39 #include "xeformula.hxx"
40 #include "cell.hxx"
41 #include "xcl97rec.hxx"
43 //___________________________________________________________________
44 // local functions
46 void lcl_WriteDateTime( XclExpStream& rStrm, const DateTime& rDateTime )
48 rStrm.SetSliceSize( 7 );
49 rStrm << (sal_uInt16) rDateTime.GetYear()
50 << (sal_uInt8) rDateTime.GetMonth()
51 << (sal_uInt8) rDateTime.GetDay()
52 << (sal_uInt8) rDateTime.GetHour()
53 << (sal_uInt8) rDateTime.GetMin()
54 << (sal_uInt8) rDateTime.GetSec();
55 rStrm.SetSliceSize( 0 );
58 // write string and fill rest of <nLength> with zero bytes
59 // <nLength> is without string header
60 void lcl_WriteFixedString( XclExpStream& rStrm, const XclExpString& rString, sal_Size nLength )
62 sal_Size nStrBytes = rString.GetBufferSize();
63 DBG_ASSERT( nLength >= nStrBytes, "lcl_WriteFixedString - String too long" );
64 if( rString.Len() > 0 )
65 rStrm << rString;
66 if( nLength > nStrBytes )
67 rStrm.WriteZeroBytes( nLength - nStrBytes );
70 inline void lcl_GenerateGUID( sal_uInt8* pGUID, sal_Bool& rValidGUID )
72 rtl_createUuid( pGUID, rValidGUID ? pGUID : NULL, sal_False );
73 rValidGUID = sal_True;
76 inline void lcl_WriteGUID( XclExpStream& rStrm, const sal_uInt8* pGUID )
78 rStrm.SetSliceSize( 16 );
79 for( sal_Size nIndex = 0; nIndex < 16; nIndex++ )
80 rStrm << pGUID[ nIndex ];
81 rStrm.SetSliceSize( 0 );
84 //___________________________________________________________________
86 XclExpUserBView::XclExpUserBView( const String& rUsername, const sal_uInt8* pGUID ) :
87 sUsername( rUsername )
89 memcpy( aGUID, pGUID, 16 );
92 void XclExpUserBView::SaveCont( XclExpStream& rStrm )
94 rStrm << (sal_uInt32) 0xFF078014
95 << (sal_uInt32) 0x00000001;
96 lcl_WriteGUID( rStrm, aGUID );
97 rStrm.WriteZeroBytes( 8 );
98 rStrm << (sal_uInt32) 1200
99 << (sal_uInt32) 1000
100 << (sal_uInt16) 1000
101 << (sal_uInt16) 0x0CF7
102 << (sal_uInt16) 0x0000
103 << (sal_uInt16) 0x0001
104 << (sal_uInt16) 0x0000;
105 if( sUsername.Len() > 0 )
106 rStrm << sUsername;
109 UINT16 XclExpUserBView::GetNum() const
111 return 0x01A9;
114 sal_Size XclExpUserBView::GetLen() const
116 return 50 + ((sUsername.Len() > 0) ? sUsername.GetSize() : 0);
119 //___________________________________________________________________
121 XclExpUserBViewList::XclExpUserBViewList( const ScChangeTrack& rChangeTrack )
123 sal_uInt8 aGUID[ 16 ];
124 sal_Bool bValidGUID = sal_False;
125 const ScStrCollection& rStrColl = rChangeTrack.GetUserCollection();
126 for( USHORT nIndex = 0; nIndex < rStrColl.GetCount(); nIndex++ )
128 const StrData* pStrData = (const StrData*) rStrColl.At( nIndex );
129 lcl_GenerateGUID( aGUID, bValidGUID );
130 if( pStrData )
131 List::Insert( new XclExpUserBView( pStrData->GetString(), aGUID ), LIST_APPEND );
135 XclExpUserBViewList::~XclExpUserBViewList()
137 for( XclExpUserBView* pRec = _First(); pRec; pRec = _Next() )
138 delete pRec;
141 void XclExpUserBViewList::Save( XclExpStream& rStrm )
143 for( XclExpUserBView* pRec = _First(); pRec; pRec = _Next() )
144 pRec->Save( rStrm );
147 //___________________________________________________________________
149 XclExpUsersViewBegin::XclExpUsersViewBegin( const sal_uInt8* pGUID, sal_uInt32 nTab ) :
150 nCurrTab( nTab )
152 memcpy( aGUID, pGUID, 16 );
155 void XclExpUsersViewBegin::SaveCont( XclExpStream& rStrm )
157 lcl_WriteGUID( rStrm, aGUID );
158 rStrm << nCurrTab
159 << (sal_uInt32) 100
160 << (sal_uInt32) 64
161 << (sal_uInt32) 3
162 << (sal_uInt32) 0x0000003C
163 << (sal_uInt16) 0
164 << (sal_uInt16) 3
165 << (sal_uInt16) 0
166 << (sal_uInt16) 3
167 << (double) 0
168 << (double) 0
169 << (sal_Int16) -1
170 << (sal_Int16) -1;
173 UINT16 XclExpUsersViewBegin::GetNum() const
175 return 0x01AA;
178 sal_Size XclExpUsersViewBegin::GetLen() const
180 return 64;
183 //___________________________________________________________________
185 void XclExpUsersViewEnd::SaveCont( XclExpStream& rStrm )
187 rStrm << (sal_uInt16) 0x0001;
190 UINT16 XclExpUsersViewEnd::GetNum() const
192 return 0x01AB;
195 sal_Size XclExpUsersViewEnd::GetLen() const
197 return 2;
200 //___________________________________________________________________
202 void XclExpChTr0x0191::SaveCont( XclExpStream& rStrm )
204 rStrm << (sal_uInt16) 0x0000;
207 UINT16 XclExpChTr0x0191::GetNum() const
209 return 0x0191;
212 sal_Size XclExpChTr0x0191::GetLen() const
214 return 2;
217 //___________________________________________________________________
219 void XclExpChTr0x0198::SaveCont( XclExpStream& rStrm )
221 rStrm << (sal_uInt16) 0x0006
222 << (sal_uInt16) 0x0000;
225 UINT16 XclExpChTr0x0198::GetNum() const
227 return 0x0198;
230 sal_Size XclExpChTr0x0198::GetLen() const
232 return 4;
235 //___________________________________________________________________
237 void XclExpChTr0x0192::SaveCont( XclExpStream& rStrm )
239 rStrm << sal_uInt16( 0x0022 );
240 rStrm.WriteZeroBytes( 510 );
243 UINT16 XclExpChTr0x0192::GetNum() const
245 return 0x0192;
248 sal_Size XclExpChTr0x0192::GetLen() const
250 return 512;
253 //___________________________________________________________________
255 void XclExpChTr0x0197::SaveCont( XclExpStream& rStrm )
257 rStrm << (sal_uInt16) 0x0000;
260 UINT16 XclExpChTr0x0197::GetNum() const
262 return 0x0197;
265 sal_Size XclExpChTr0x0197::GetLen() const
267 return 2;
270 //___________________________________________________________________
272 XclExpChTrEmpty::~XclExpChTrEmpty()
276 UINT16 XclExpChTrEmpty::GetNum() const
278 return nRecNum;
281 sal_Size XclExpChTrEmpty::GetLen() const
283 return 0;
286 //___________________________________________________________________
288 XclExpChTr0x0195::~XclExpChTr0x0195()
292 void XclExpChTr0x0195::SaveCont( XclExpStream& rStrm )
294 rStrm.WriteZeroBytes( 162 );
297 UINT16 XclExpChTr0x0195::GetNum() const
299 return 0x0195;
302 sal_Size XclExpChTr0x0195::GetLen() const
304 return 162;
307 //___________________________________________________________________
309 XclExpChTr0x0194::~XclExpChTr0x0194()
313 void XclExpChTr0x0194::SaveCont( XclExpStream& rStrm )
315 rStrm << (sal_uInt32) 0;
316 lcl_WriteDateTime( rStrm, aDateTime );
317 rStrm << (sal_uInt8) 0;
318 lcl_WriteFixedString( rStrm, sUsername, 147 );
321 UINT16 XclExpChTr0x0194::GetNum() const
323 return 0x0194;
326 sal_Size XclExpChTr0x0194::GetLen() const
328 return 162;
331 //___________________________________________________________________
333 XclExpChTrHeader::~XclExpChTrHeader()
337 void XclExpChTrHeader::SaveCont( XclExpStream& rStrm )
339 rStrm << (sal_uInt16) 0x0006
340 << (sal_uInt16) 0x0000
341 << (sal_uInt16) 0x000D;
342 lcl_WriteGUID( rStrm, aGUID );
343 lcl_WriteGUID( rStrm, aGUID );
344 rStrm << nCount
345 << (sal_uInt16) 0x0001
346 << (sal_uInt32) 0x00000000
347 << (sal_uInt16) 0x001E;
350 UINT16 XclExpChTrHeader::GetNum() const
352 return 0x0196;
355 sal_Size XclExpChTrHeader::GetLen() const
357 return 50;
360 //___________________________________________________________________
362 XclExpChTrInfo::~XclExpChTrInfo()
366 void XclExpChTrInfo::SaveCont( XclExpStream& rStrm )
368 rStrm << (sal_uInt32) 0xFFFFFFFF
369 << (sal_uInt32) 0x00000000
370 << (sal_uInt32) 0x00000020
371 << (sal_uInt16) 0xFFFF;
372 lcl_WriteGUID( rStrm, aGUID );
373 rStrm << (sal_uInt16) 0x04B0;
374 lcl_WriteFixedString( rStrm, sUsername, 113 );
375 lcl_WriteDateTime( rStrm, aDateTime );
376 rStrm << (sal_uInt8) 0x0000
377 << (sal_uInt16) 0x0002;
380 UINT16 XclExpChTrInfo::GetNum() const
382 return 0x0138;
385 sal_Size XclExpChTrInfo::GetLen() const
387 return 158;
390 //___________________________________________________________________
392 XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( sal_uInt16 nCount ) :
393 nBufSize( nCount ),
394 nLastId( nCount )
396 pBuffer = new sal_uInt16[ nBufSize ];
397 memset( pBuffer, 0, sizeof(sal_uInt16) * nBufSize );
398 pLast = pBuffer + nBufSize - 1;
401 XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( const XclExpChTrTabIdBuffer& rCopy ) :
402 nBufSize( rCopy.nBufSize ),
403 nLastId( rCopy.nLastId )
405 pBuffer = new sal_uInt16[ nBufSize ];
406 memcpy( pBuffer, rCopy.pBuffer, sizeof(sal_uInt16) * nBufSize );
407 pLast = pBuffer + nBufSize - 1;
410 XclExpChTrTabIdBuffer::~XclExpChTrTabIdBuffer()
412 delete[] pBuffer;
415 void XclExpChTrTabIdBuffer::InitFill( sal_uInt16 nIndex )
417 DBG_ASSERT( nIndex < nLastId, "XclExpChTrTabIdBuffer::Insert - out of range" );
419 sal_uInt16 nFreeCount = 0;
420 for( sal_uInt16* pElem = pBuffer; pElem <= pLast; pElem++ )
422 if( !*pElem )
423 nFreeCount++;
424 if( nFreeCount > nIndex )
426 *pElem = nLastId--;
427 return;
432 void XclExpChTrTabIdBuffer::InitFillup()
434 sal_uInt16 nFreeCount = 1;
435 for( sal_uInt16* pElem = pBuffer; pElem <= pLast; pElem++ )
436 if( !*pElem )
437 *pElem = nFreeCount++;
438 nLastId = nBufSize;
441 sal_uInt16 XclExpChTrTabIdBuffer::GetId( sal_uInt16 nIndex ) const
443 DBG_ASSERT( nIndex < nBufSize, "XclExpChTrTabIdBuffer::GetId - out of range" );
444 return pBuffer[ nIndex ];
447 void XclExpChTrTabIdBuffer::Remove()
449 DBG_ASSERT( pBuffer <= pLast, "XclExpChTrTabIdBuffer::Remove - buffer empty" );
450 sal_uInt16* pElem = pBuffer;
451 while( (pElem <= pLast) && (*pElem != nLastId) )
452 pElem++;
453 while( pElem < pLast )
455 *pElem = *(pElem + 1);
456 pElem++;
458 pLast--;
459 nLastId--;
462 //___________________________________________________________________
464 XclExpChTrTabIdBufferList::~XclExpChTrTabIdBufferList()
466 for( XclExpChTrTabIdBuffer* pBuffer = First(); pBuffer; pBuffer = Next() )
467 delete pBuffer;
470 //___________________________________________________________________
472 XclExpChTrTabId::XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer ) :
473 nTabCount( rBuffer.GetBufferCount() )
475 pBuffer = new sal_uInt16[ nTabCount ];
476 rBuffer.GetBufferCopy( pBuffer );
479 XclExpChTrTabId::~XclExpChTrTabId()
481 Clear();
484 void XclExpChTrTabId::Copy( const XclExpChTrTabIdBuffer& rBuffer )
486 Clear();
487 nTabCount = rBuffer.GetBufferCount();
488 pBuffer = new sal_uInt16[ nTabCount ];
489 rBuffer.GetBufferCopy( pBuffer );
492 void XclExpChTrTabId::SaveCont( XclExpStream& rStrm )
494 rStrm.EnableEncryption();
495 if( pBuffer )
496 for( sal_uInt16* pElem = pBuffer; pElem < (pBuffer + nTabCount); pElem++ )
497 rStrm << *pElem;
498 else
499 for( sal_uInt16 nIndex = 1; nIndex <= nTabCount; nIndex++ )
500 rStrm << nIndex;
503 UINT16 XclExpChTrTabId::GetNum() const
505 return 0x013D;
508 sal_Size XclExpChTrTabId::GetLen() const
510 return nTabCount << 1;
513 //___________________________________________________________________
515 // ! does not copy additional actions
516 XclExpChTrAction::XclExpChTrAction( const XclExpChTrAction& rCopy ) :
517 ExcRecord( rCopy ),
518 sUsername( rCopy.sUsername ),
519 aDateTime( rCopy.aDateTime ),
520 nIndex( 0 ),
521 pAddAction( 0 ),
522 bAccepted( rCopy.bAccepted ),
523 rTabInfo( rCopy.rTabInfo ),
524 rIdBuffer( rCopy.rIdBuffer ),
525 nLength( rCopy.nLength ),
526 nOpCode( rCopy.nOpCode ),
527 bForceInfo( rCopy.bForceInfo )
531 XclExpChTrAction::XclExpChTrAction(
532 const ScChangeAction& rAction,
533 const XclExpRoot& rRoot,
534 const XclExpChTrTabIdBuffer& rTabIdBuffer,
535 sal_uInt16 nNewOpCode ) :
536 sUsername( rAction.GetUser() ),
537 aDateTime( rAction.GetDateTime() ),
538 nIndex( 0 ),
539 pAddAction( NULL ),
540 bAccepted( rAction.IsAccepted() ),
541 rTabInfo( rRoot.GetTabInfo() ),
542 rIdBuffer( rTabIdBuffer ),
543 nLength( 0 ),
544 nOpCode( nNewOpCode ),
545 bForceInfo( sal_False )
547 aDateTime.SetSec( 0 );
548 aDateTime.Set100Sec( 0 );
551 XclExpChTrAction::~XclExpChTrAction()
553 if( pAddAction )
554 delete pAddAction;
557 void XclExpChTrAction::SetAddAction( XclExpChTrAction* pAction )
559 if( pAddAction )
560 pAddAction->SetAddAction( pAction );
561 else
562 pAddAction = pAction;
565 void XclExpChTrAction::AddDependentContents(
566 const ScChangeAction& rAction,
567 const XclExpRoot& rRoot,
568 ScChangeTrack& rChangeTrack )
570 ScChangeActionTable aActionTable;
571 rChangeTrack.GetDependents( (ScChangeAction*)(&rAction), aActionTable );
572 for( const ScChangeAction* pDepAction = aActionTable.First(); pDepAction; pDepAction = aActionTable.Next() )
573 if( pDepAction->GetType() == SC_CAT_CONTENT )
574 SetAddAction( new XclExpChTrCellContent(
575 *((const ScChangeActionContent*) pDepAction), rRoot, rIdBuffer ) );
578 void XclExpChTrAction::SetIndex( sal_uInt32& rIndex )
580 nIndex = rIndex++;
583 void XclExpChTrAction::SaveCont( XclExpStream& rStrm )
585 DBG_ASSERT( nOpCode != EXC_CHTR_OP_UNKNOWN, "XclExpChTrAction::SaveCont - unknown action" );
586 rStrm << nLength
587 << nIndex
588 << nOpCode
589 << (sal_uInt16)(bAccepted ? EXC_CHTR_ACCEPT : EXC_CHTR_NOTHING);
590 SaveActionData( rStrm );
593 void XclExpChTrAction::PrepareSaveAction( XclExpStream& /*rStrm*/ ) const
597 void XclExpChTrAction::CompleteSaveAction( XclExpStream& /*rStrm*/ ) const
601 void XclExpChTrAction::Save( XclExpStream& rStrm )
603 PrepareSaveAction( rStrm );
604 ExcRecord::Save( rStrm );
605 if( pAddAction )
606 pAddAction->Save( rStrm );
607 CompleteSaveAction( rStrm );
610 sal_Size XclExpChTrAction::GetLen() const
612 return GetHeaderByteCount() + GetActionByteCount();
615 //___________________________________________________________________
617 XclExpChTrData::XclExpChTrData() :
618 pString( NULL ),
619 fValue( 0.0 ),
620 nRKValue( 0 ),
621 nType( EXC_CHTR_TYPE_EMPTY ),
622 nSize( 0 )
626 XclExpChTrData::~XclExpChTrData()
628 Clear();
631 void XclExpChTrData::Clear()
633 DELETEZ( pString );
634 mxTokArr.reset();
635 maRefLog.clear();
636 fValue = 0.0;
637 nRKValue = 0;
638 nType = EXC_CHTR_TYPE_EMPTY;
639 nSize = 0;
642 void XclExpChTrData::WriteFormula( XclExpStream& rStrm, const XclExpChTrTabIdBuffer& rTabIdBuffer )
644 DBG_ASSERT( mxTokArr.is() && !mxTokArr->Empty(), "XclExpChTrData::Write - no formula" );
645 rStrm << *mxTokArr;
647 for( XclExpRefLog::const_iterator aIt = maRefLog.begin(), aEnd = maRefLog.end(); aIt != aEnd; ++aIt )
649 if( aIt->mpUrl && aIt->mpFirstTab )
651 rStrm << *aIt->mpUrl << (sal_uInt8) 0x01 << *aIt->mpFirstTab << (sal_uInt8) 0x02;
653 else
655 bool bSingleTab = aIt->mnFirstXclTab == aIt->mnLastXclTab;
656 rStrm.SetSliceSize( bSingleTab ? 6 : 8 );
657 rStrm << (sal_uInt8) 0x01 << (sal_uInt8) 0x02 << (sal_uInt8) 0x00;
658 rStrm << rTabIdBuffer.GetId( aIt->mnFirstXclTab );
659 if( bSingleTab )
660 rStrm << (sal_uInt8) 0x02;
661 else
662 rStrm << (sal_uInt8) 0x00 << rTabIdBuffer.GetId( aIt->mnLastXclTab );
665 rStrm.SetSliceSize( 0 );
666 rStrm << (sal_uInt8) 0x00;
669 void XclExpChTrData::Write( XclExpStream& rStrm, const XclExpChTrTabIdBuffer& rTabIdBuffer )
671 switch( nType )
673 case EXC_CHTR_TYPE_RK:
674 rStrm << nRKValue;
675 break;
676 case EXC_CHTR_TYPE_DOUBLE:
677 rStrm << fValue;
678 break;
679 case EXC_CHTR_TYPE_STRING:
680 DBG_ASSERT( pString, "XclExpChTrData::Write - no string" );
681 rStrm << *pString;
682 break;
683 case EXC_CHTR_TYPE_FORMULA:
684 WriteFormula( rStrm, rTabIdBuffer );
685 break;
689 //___________________________________________________________________
691 XclExpChTrCellContent::XclExpChTrCellContent(
692 const ScChangeActionContent& rAction,
693 const XclExpRoot& rRoot,
694 const XclExpChTrTabIdBuffer& rTabIdBuffer ) :
695 XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_CELL ),
696 XclExpRoot( rRoot ),
697 pOldData( 0 ),
698 pNewData( 0 ),
699 aPosition( rAction.GetBigRange().MakeRange().aStart )
701 sal_uInt32 nDummy32;
702 sal_uInt16 nDummy16;
703 GetCellData( rAction.GetOldCell(), pOldData, nDummy32, nOldLength );
704 GetCellData( rAction.GetNewCell(), pNewData, nLength, nDummy16 );
707 XclExpChTrCellContent::~XclExpChTrCellContent()
709 if( pOldData )
710 delete pOldData;
711 if( pNewData )
712 delete pNewData;
715 void XclExpChTrCellContent::MakeEmptyChTrData( XclExpChTrData*& rpData )
717 if( rpData )
718 rpData->Clear();
719 else
720 rpData = new XclExpChTrData;
723 void XclExpChTrCellContent::GetCellData(
724 const ScBaseCell* pScCell,
725 XclExpChTrData*& rpData,
726 sal_uInt32& rXclLength1,
727 sal_uInt16& rXclLength2 )
729 MakeEmptyChTrData( rpData );
730 rXclLength1 = 0x0000003A;
731 rXclLength2 = 0x0000;
733 if( !pScCell )
735 delete rpData;
736 rpData = NULL;
737 return;
740 switch( pScCell->GetCellType() )
742 case CELLTYPE_VALUE:
744 rpData->fValue = ((const ScValueCell*) pScCell)->GetValue();
745 if( XclTools::GetRKFromDouble( rpData->nRKValue, rpData->fValue ) )
747 rpData->nType = EXC_CHTR_TYPE_RK;
748 rpData->nSize = 4;
749 rXclLength1 = 0x0000003E;
750 rXclLength2 = 0x0004;
752 else
754 rpData->nType = EXC_CHTR_TYPE_DOUBLE;
755 rpData->nSize = 8;
756 rXclLength1 = 0x00000042;
757 rXclLength2 = 0x0008;
760 break;
761 case CELLTYPE_STRING:
762 case CELLTYPE_EDIT:
764 String sCellStr;
765 if( pScCell->GetCellType() == CELLTYPE_STRING )
766 ((const ScStringCell*) pScCell)->GetString( sCellStr );
767 else
768 ((const ScEditCell*) pScCell)->GetString( sCellStr );
769 rpData->pString = new XclExpString( sCellStr, EXC_STR_DEFAULT, 32766 );
770 rpData->nType = EXC_CHTR_TYPE_STRING;
771 rpData->nSize = 3 + rpData->pString->GetSize();
772 rXclLength1 = 64 + (sCellStr.Len() << 1);
773 rXclLength2 = 6 + (sal_uInt16)(sCellStr.Len() << 1);
775 break;
776 case CELLTYPE_FORMULA:
778 const ScFormulaCell* pFmlCell = (const ScFormulaCell*) pScCell;
779 const ScTokenArray* pTokenArray = pFmlCell->GetCode();
780 if( pTokenArray )
782 XclExpRefLog& rRefLog = rpData->maRefLog;
783 rpData->mxTokArr = GetFormulaCompiler().CreateFormula(
784 EXC_FMLATYPE_CELL, *pTokenArray, &pFmlCell->aPos, &rRefLog );
785 rpData->nType = EXC_CHTR_TYPE_FORMULA;
786 sal_Size nSize = rpData->mxTokArr->GetSize() + 3;
788 for( XclExpRefLog::const_iterator aIt = rRefLog.begin(), aEnd = rRefLog.end(); aIt != aEnd; ++aIt )
790 if( aIt->mpUrl && aIt->mpFirstTab )
791 nSize += aIt->mpUrl->GetSize() + aIt->mpFirstTab->GetSize() + 2;
792 else
793 nSize += (aIt->mnFirstXclTab == aIt->mnLastXclTab) ? 6 : 8;
795 rpData->nSize = ::std::min< sal_Size >( nSize, 0xFFFF );
796 rXclLength1 = 0x00000052;
797 rXclLength2 = 0x0018;
800 break;
801 default:;
805 void XclExpChTrCellContent::SaveActionData( XclExpStream& rStrm ) const
807 WriteTabId( rStrm, aPosition.Tab() );
808 rStrm << (sal_uInt16)((pOldData ? (pOldData->nType << 3) : 0x0000) | (pNewData ? pNewData->nType : 0x0000))
809 << (sal_uInt16) 0x0000;
810 Write2DAddress( rStrm, aPosition );
811 rStrm << nOldLength
812 << (sal_uInt32) 0x00000000;
813 if( pOldData )
814 pOldData->Write( rStrm, rIdBuffer );
815 if( pNewData )
816 pNewData->Write( rStrm, rIdBuffer );
819 UINT16 XclExpChTrCellContent::GetNum() const
821 return 0x013B;
824 sal_Size XclExpChTrCellContent::GetActionByteCount() const
826 sal_Size nLen = 16;
827 if( pOldData )
828 nLen += pOldData->nSize;
829 if( pNewData )
830 nLen += pNewData->nSize;
831 return nLen;
834 //___________________________________________________________________
836 XclExpChTrInsert::XclExpChTrInsert(
837 const ScChangeAction& rAction,
838 const XclExpRoot& rRoot,
839 const XclExpChTrTabIdBuffer& rTabIdBuffer,
840 ScChangeTrack& rChangeTrack ) :
841 XclExpChTrAction( rAction, rRoot, rTabIdBuffer ),
842 aRange( rAction.GetBigRange().MakeRange() )
844 nLength = 0x00000030;
845 switch( rAction.GetType() )
847 case SC_CAT_INSERT_COLS: nOpCode = EXC_CHTR_OP_INSCOL; break;
848 case SC_CAT_INSERT_ROWS: nOpCode = EXC_CHTR_OP_INSROW; break;
849 case SC_CAT_DELETE_COLS: nOpCode = EXC_CHTR_OP_DELCOL; break;
850 case SC_CAT_DELETE_ROWS: nOpCode = EXC_CHTR_OP_DELROW; break;
851 default:
852 DBG_ERROR( "XclExpChTrInsert::XclExpChTrInsert - unknown action" );
855 if( nOpCode & EXC_CHTR_OP_COLFLAG )
857 aRange.aStart.SetRow( 0 );
858 aRange.aEnd.SetRow( rRoot.GetXclMaxPos().Row() );
860 else
862 aRange.aStart.SetCol( 0 );
863 aRange.aEnd.SetCol( rRoot.GetXclMaxPos().Col() );
866 if( nOpCode & EXC_CHTR_OP_DELFLAG )
868 SetAddAction( new XclExpChTr0x014A( *this ) );
869 AddDependentContents( rAction, rRoot, rChangeTrack );
873 XclExpChTrInsert::~XclExpChTrInsert()
877 void XclExpChTrInsert::SaveActionData( XclExpStream& rStrm ) const
879 WriteTabId( rStrm, aRange.aStart.Tab() );
880 rStrm << (sal_uInt16) 0x0000;
881 Write2DRange( rStrm, aRange );
882 rStrm << (sal_uInt32) 0x00000000;
885 void XclExpChTrInsert::PrepareSaveAction( XclExpStream& rStrm ) const
887 if( (nOpCode == EXC_CHTR_OP_DELROW) || (nOpCode == EXC_CHTR_OP_DELCOL) )
888 XclExpChTrEmpty( 0x0150 ).Save( rStrm );
891 void XclExpChTrInsert::CompleteSaveAction( XclExpStream& rStrm ) const
893 if( (nOpCode == EXC_CHTR_OP_DELROW) || (nOpCode == EXC_CHTR_OP_DELCOL) )
894 XclExpChTrEmpty( 0x0151 ).Save( rStrm );
897 UINT16 XclExpChTrInsert::GetNum() const
899 return 0x0137;
902 sal_Size XclExpChTrInsert::GetActionByteCount() const
904 return 16;
907 //___________________________________________________________________
909 XclExpChTrInsertTab::XclExpChTrInsertTab(
910 const ScChangeAction& rAction,
911 const XclExpRoot& rRoot,
912 const XclExpChTrTabIdBuffer& rTabIdBuffer ) :
913 XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_INSTAB ),
914 XclExpRoot( rRoot ),
915 nTab( (SCTAB) rAction.GetBigRange().aStart.Tab() )
917 nLength = 0x0000021C;
918 bForceInfo = sal_True;
921 XclExpChTrInsertTab::~XclExpChTrInsertTab()
925 void XclExpChTrInsertTab::SaveActionData( XclExpStream& rStrm ) const
927 WriteTabId( rStrm, nTab );
928 rStrm << sal_uInt32( 0 );
929 lcl_WriteFixedString( rStrm, XclExpString( GetTabInfo().GetScTabName( nTab ) ), 127 );
930 lcl_WriteDateTime( rStrm, GetDateTime() );
931 rStrm.WriteZeroBytes( 133 );
934 UINT16 XclExpChTrInsertTab::GetNum() const
936 return 0x014D;
939 sal_Size XclExpChTrInsertTab::GetActionByteCount() const
941 return 276;
944 //___________________________________________________________________
946 XclExpChTrMoveRange::XclExpChTrMoveRange(
947 const ScChangeActionMove& rAction,
948 const XclExpRoot& rRoot,
949 const XclExpChTrTabIdBuffer& rTabIdBuffer,
950 ScChangeTrack& rChangeTrack ) :
951 XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_MOVE ),
952 aDestRange( rAction.GetBigRange().MakeRange() )
954 nLength = 0x00000042;
955 aSourceRange = aDestRange;
956 sal_Int32 nDCols, nDRows, nDTabs;
957 rAction.GetDelta( nDCols, nDRows, nDTabs );
958 aSourceRange.aStart.IncRow( (SCROW) -nDRows );
959 aSourceRange.aStart.IncCol( (SCCOL) -nDCols );
960 aSourceRange.aStart.IncTab( (SCTAB) -nDTabs );
961 aSourceRange.aEnd.IncRow( (SCROW) -nDRows );
962 aSourceRange.aEnd.IncCol( (SCCOL) -nDCols );
963 aSourceRange.aEnd.IncTab( (SCTAB) -nDTabs );
964 AddDependentContents( rAction, rRoot, rChangeTrack );
967 XclExpChTrMoveRange::~XclExpChTrMoveRange()
971 void XclExpChTrMoveRange::SaveActionData( XclExpStream& rStrm ) const
973 WriteTabId( rStrm, aDestRange.aStart.Tab() );
974 Write2DRange( rStrm, aSourceRange );
975 Write2DRange( rStrm, aDestRange );
976 WriteTabId( rStrm, aSourceRange.aStart.Tab() );
977 rStrm << (sal_uInt32) 0x00000000;
980 void XclExpChTrMoveRange::PrepareSaveAction( XclExpStream& rStrm ) const
982 XclExpChTrEmpty( 0x014E ).Save( rStrm );
985 void XclExpChTrMoveRange::CompleteSaveAction( XclExpStream& rStrm ) const
987 XclExpChTrEmpty( 0x014F ).Save( rStrm );
990 UINT16 XclExpChTrMoveRange::GetNum() const
992 return 0x0140;
995 sal_Size XclExpChTrMoveRange::GetActionByteCount() const
997 return 24;
1000 //___________________________________________________________________
1002 XclExpChTr0x014A::XclExpChTr0x014A( const XclExpChTrInsert& rAction ) :
1003 XclExpChTrInsert( rAction )
1005 nLength = 0x00000026;
1006 nOpCode = EXC_CHTR_OP_FORMAT;
1009 XclExpChTr0x014A::~XclExpChTr0x014A()
1013 void XclExpChTr0x014A::SaveActionData( XclExpStream& rStrm ) const
1015 WriteTabId( rStrm, aRange.aStart.Tab() );
1016 rStrm << (sal_uInt16) 0x0003
1017 << (sal_uInt16) 0x0001;
1018 Write2DRange( rStrm, aRange );
1021 UINT16 XclExpChTr0x014A::GetNum() const
1023 return 0x014A;
1026 sal_Size XclExpChTr0x014A::GetActionByteCount() const
1028 return 14;
1031 //___________________________________________________________________
1033 XclExpChTrActionStack::~XclExpChTrActionStack()
1035 while( XclExpChTrAction* pRec = Pop() )
1036 delete pRec;
1039 void XclExpChTrActionStack::Push( XclExpChTrAction* pNewRec )
1041 DBG_ASSERT( pNewRec, "XclExpChTrActionStack::Push - NULL pointer" );
1042 if( pNewRec )
1043 Stack::Push( pNewRec );
1046 //___________________________________________________________________
1048 XclExpChTrRecordList::~XclExpChTrRecordList()
1050 for( ExcRecord* pRec = First(); pRec; pRec = Next() )
1051 delete pRec;
1054 void XclExpChTrRecordList::Append( ExcRecord* pNewRec )
1056 DBG_ASSERT( pNewRec, "XclExpChTrRecordList::Append - NULL pointer" );
1057 if( pNewRec )
1058 List::Insert( pNewRec, LIST_APPEND );
1061 void XclExpChTrRecordList::Save( XclExpStream& rStrm )
1063 for( ExcRecord* pRec = First(); pRec; pRec = Next() )
1064 pRec->Save( rStrm );
1067 //___________________________________________________________________
1069 XclExpChangeTrack::XclExpChangeTrack( const XclExpRoot& rRoot ) :
1070 XclExpRoot( rRoot ),
1071 aRecList(),
1072 aActionStack(),
1073 aTabIdBufferList(),
1074 pTabIdBuffer( NULL ),
1075 pTempDoc( NULL ),
1076 nNewAction( 1 ),
1077 pHeader( NULL ),
1078 bValidGUID( sal_False )
1080 DBG_ASSERT( GetOldRoot().pTabId, "XclExpChangeTrack::XclExpChangeTrack - root data incomplete" );
1081 if( !GetOldRoot().pTabId )
1082 return;
1084 ScChangeTrack* pTempChangeTrack = CreateTempChangeTrack();
1085 if (!pTempChangeTrack)
1086 return;
1088 pTabIdBuffer = new XclExpChTrTabIdBuffer( GetTabInfo().GetXclTabCount() );
1089 aTabIdBufferList.Append( pTabIdBuffer );
1091 // calculate final table order (tab id list)
1092 const ScChangeAction* pScAction;
1093 for( pScAction = pTempChangeTrack->GetLast(); pScAction; pScAction = pScAction->GetPrev() )
1095 if( pScAction->GetType() == SC_CAT_INSERT_TABS )
1097 SCTAB nScTab = static_cast< SCTAB >( pScAction->GetBigRange().aStart.Tab() );
1098 pTabIdBuffer->InitFill( GetTabInfo().GetXclTab( nScTab ) );
1101 pTabIdBuffer->InitFillup();
1102 GetOldRoot().pTabId->Copy( *pTabIdBuffer );
1104 // get actions in reverse order
1105 pScAction = pTempChangeTrack->GetLast();
1106 while( pScAction )
1108 PushActionRecord( *pScAction );
1109 const ScChangeAction* pPrevAction = pScAction->GetPrev();
1110 pTempChangeTrack->Undo( pScAction->GetActionNumber(), pScAction->GetActionNumber() );
1111 pScAction = pPrevAction;
1114 // build record list
1115 pHeader = new XclExpChTrHeader;
1116 aRecList.Append( pHeader );
1117 aRecList.Append( new XclExpChTr0x0195 );
1118 aRecList.Append( new XclExpChTr0x0194( *pTempChangeTrack ) );
1120 String sLastUsername;
1121 DateTime aLastDateTime;
1122 sal_uInt32 nIndex = 1;
1123 while( XclExpChTrAction* pAction = aActionStack.Pop() )
1125 if( (nIndex == 1) || pAction->ForceInfoRecord() ||
1126 (pAction->GetUsername() != sLastUsername) ||
1127 (pAction->GetDateTime() != aLastDateTime) )
1129 lcl_GenerateGUID( aGUID, bValidGUID );
1130 sLastUsername = pAction->GetUsername();
1131 aLastDateTime = pAction->GetDateTime();
1132 aRecList.Append( new XclExpChTrInfo( sLastUsername, aLastDateTime, aGUID ) );
1133 aRecList.Append( new XclExpChTrTabId( pAction->GetTabIdBuffer() ) );
1134 pHeader->SetGUID( aGUID );
1136 pAction->SetIndex( nIndex );
1137 aRecList.Append( pAction );
1140 pHeader->SetGUID( aGUID );
1141 pHeader->SetCount( nIndex - 1 );
1142 aRecList.Append( new ExcEof );
1145 XclExpChangeTrack::~XclExpChangeTrack()
1147 if( pTempDoc )
1148 delete pTempDoc;
1151 ScChangeTrack* XclExpChangeTrack::CreateTempChangeTrack()
1153 // get original change track
1154 ScChangeTrack* pOrigChangeTrack = GetDoc().GetChangeTrack();
1155 DBG_ASSERT( pOrigChangeTrack, "XclExpChangeTrack::CreateTempChangeTrack - no change track data" );
1156 if( !pOrigChangeTrack )
1157 return NULL;
1159 // create empty document
1160 pTempDoc = new ScDocument;
1161 DBG_ASSERT( pTempDoc, "XclExpChangeTrack::CreateTempChangeTrack - no temp document" );
1162 if( !pTempDoc )
1163 return NULL;
1165 // adjust table count
1166 SCTAB nOrigCount = GetDoc().GetTableCount();
1167 String sTabName;
1168 for( sal_Int32 nIndex = 0; nIndex < nOrigCount; nIndex++ )
1170 pTempDoc->CreateValidTabName( sTabName );
1171 pTempDoc->InsertTab( SC_TAB_APPEND, sTabName );
1173 DBG_ASSERT( nOrigCount == pTempDoc->GetTableCount(),
1174 "XclExpChangeTrack::CreateTempChangeTrack - table count mismatch" );
1175 if( nOrigCount != pTempDoc->GetTableCount() )
1176 return sal_False;
1178 return pOrigChangeTrack->Clone(pTempDoc);
1181 void XclExpChangeTrack::PushActionRecord( const ScChangeAction& rAction )
1183 XclExpChTrAction* pXclAction = NULL;
1184 ScChangeTrack* pTempChangeTrack = pTempDoc->GetChangeTrack();
1185 switch( rAction.GetType() )
1187 case SC_CAT_CONTENT:
1188 pXclAction = new XclExpChTrCellContent( (const ScChangeActionContent&) rAction, GetRoot(), *pTabIdBuffer );
1189 break;
1190 case SC_CAT_INSERT_ROWS:
1191 case SC_CAT_INSERT_COLS:
1192 case SC_CAT_DELETE_ROWS:
1193 case SC_CAT_DELETE_COLS:
1194 if (pTempChangeTrack)
1195 pXclAction = new XclExpChTrInsert( rAction, GetRoot(), *pTabIdBuffer, *pTempChangeTrack );
1196 break;
1197 case SC_CAT_INSERT_TABS:
1199 pXclAction = new XclExpChTrInsertTab( rAction, GetRoot(), *pTabIdBuffer );
1200 XclExpChTrTabIdBuffer* pNewBuffer = new XclExpChTrTabIdBuffer( *pTabIdBuffer );
1201 pNewBuffer->Remove();
1202 aTabIdBufferList.Append( pNewBuffer );
1203 pTabIdBuffer = pNewBuffer;
1205 break;
1206 case SC_CAT_MOVE:
1207 if (pTempChangeTrack)
1208 pXclAction = new XclExpChTrMoveRange( (const ScChangeActionMove&) rAction, GetRoot(), *pTabIdBuffer, *pTempChangeTrack );
1209 break;
1210 default:;
1212 if( pXclAction )
1213 aActionStack.Push( pXclAction );
1216 sal_Bool XclExpChangeTrack::WriteUserNamesStream()
1218 sal_Bool bRet = sal_False;
1219 SotStorageStreamRef xSvStrm = OpenStream( EXC_STREAM_USERNAMES );
1220 DBG_ASSERT( xSvStrm.Is(), "XclExpChangeTrack::WriteUserNamesStream - no stream" );
1221 if( xSvStrm.Is() )
1223 XclExpStream aXclStrm( *xSvStrm, GetRoot() );
1224 XclExpChTr0x0191().Save( aXclStrm );
1225 XclExpChTr0x0198().Save( aXclStrm );
1226 XclExpChTr0x0192().Save( aXclStrm );
1227 XclExpChTr0x0197().Save( aXclStrm );
1228 xSvStrm->Commit();
1229 bRet = sal_True;
1231 return bRet;
1234 void XclExpChangeTrack::Write()
1236 if( !aRecList.Count() )
1237 return;
1239 if( WriteUserNamesStream() )
1241 SotStorageStreamRef xSvStrm = OpenStream( EXC_STREAM_REVLOG );
1242 DBG_ASSERT( xSvStrm.Is(), "XclExpChangeTrack::Write - no stream" );
1243 if( xSvStrm.Is() )
1245 XclExpStream aXclStrm( *xSvStrm, GetRoot(), EXC_MAXRECSIZE_BIFF8 + 8 );
1246 aRecList.Save( aXclStrm );
1247 xSvStrm->Commit();