1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 //___________________________________________________________________
29 
30 #include <sot/storage.hxx>
31 #include "XclExpChangeTrack.hxx"
32 #include "xeformula.hxx"
33 #include "cell.hxx"
34 #include "xcl97rec.hxx"
35 
36 //___________________________________________________________________
37 // local functions
38 
lcl_WriteDateTime(XclExpStream & rStrm,const DateTime & rDateTime)39 void lcl_WriteDateTime( XclExpStream& rStrm, const DateTime& rDateTime )
40 {
41     rStrm.SetSliceSize( 7 );
42 	rStrm	<< (sal_uInt16)	rDateTime.GetYear()
43 			<< (sal_uInt8)	rDateTime.GetMonth()
44 			<< (sal_uInt8)	rDateTime.GetDay()
45 			<< (sal_uInt8)	rDateTime.GetHour()
46 			<< (sal_uInt8)	rDateTime.GetMin()
47 			<< (sal_uInt8)	rDateTime.GetSec();
48     rStrm.SetSliceSize( 0 );
49 }
50 
51 // write string and fill rest of <nLength> with zero bytes
52 // <nLength> is without string header
lcl_WriteFixedString(XclExpStream & rStrm,const XclExpString & rString,sal_Size nLength)53 void lcl_WriteFixedString( XclExpStream& rStrm, const XclExpString& rString, sal_Size nLength )
54 {
55     sal_Size nStrBytes = rString.GetBufferSize();
56 	DBG_ASSERT( nLength >= nStrBytes, "lcl_WriteFixedString - String too long" );
57     if( rString.Len() > 0 )
58         rStrm << rString;
59 	if( nLength > nStrBytes )
60         rStrm.WriteZeroBytes( nLength - nStrBytes );
61 }
62 
lcl_GenerateGUID(sal_uInt8 * pGUID,sal_Bool & rValidGUID)63 inline void lcl_GenerateGUID( sal_uInt8* pGUID, sal_Bool& rValidGUID )
64 {
65 	rtl_createUuid( pGUID, rValidGUID ? pGUID : NULL, sal_False );
66 	rValidGUID = sal_True;
67 }
68 
lcl_WriteGUID(XclExpStream & rStrm,const sal_uInt8 * pGUID)69 inline void lcl_WriteGUID( XclExpStream& rStrm, const sal_uInt8* pGUID )
70 {
71     rStrm.SetSliceSize( 16 );
72     for( sal_Size nIndex = 0; nIndex < 16; nIndex++ )
73 		rStrm << pGUID[ nIndex ];
74     rStrm.SetSliceSize( 0 );
75 }
76 
77 //___________________________________________________________________
78 
XclExpUserBView(const String & rUsername,const sal_uInt8 * pGUID)79 XclExpUserBView::XclExpUserBView( const String& rUsername, const sal_uInt8* pGUID ) :
80     sUsername( rUsername )
81 {
82 	memcpy( aGUID, pGUID, 16 );
83 }
84 
SaveCont(XclExpStream & rStrm)85 void XclExpUserBView::SaveCont( XclExpStream& rStrm )
86 {
87 	rStrm	<< (sal_uInt32)	0xFF078014
88 			<< (sal_uInt32)	0x00000001;
89 	lcl_WriteGUID( rStrm, aGUID );
90     rStrm.WriteZeroBytes( 8 );
91     rStrm   << (sal_uInt32) 1200
92 			<< (sal_uInt32)	1000
93 			<< (sal_uInt16)	1000
94 			<< (sal_uInt16)	0x0CF7
95 			<< (sal_uInt16)	0x0000
96 			<< (sal_uInt16)	0x0001
97 			<< (sal_uInt16)	0x0000;
98     if( sUsername.Len() > 0 )
99         rStrm << sUsername;
100 }
101 
GetNum() const102 sal_uInt16 XclExpUserBView::GetNum() const
103 {
104 	return 0x01A9;
105 }
106 
GetLen() const107 sal_Size XclExpUserBView::GetLen() const
108 {
109     return 50 + ((sUsername.Len() > 0) ? sUsername.GetSize() : 0);
110 }
111 
112 //___________________________________________________________________
113 
XclExpUserBViewList(const ScChangeTrack & rChangeTrack)114 XclExpUserBViewList::XclExpUserBViewList( const ScChangeTrack& rChangeTrack )
115 {
116 	sal_uInt8 aGUID[ 16 ];
117 	sal_Bool bValidGUID = sal_False;
118 	const ScStrCollection& rStrColl = rChangeTrack.GetUserCollection();
119 	for( sal_uInt16 nIndex = 0; nIndex < rStrColl.GetCount(); nIndex++ )
120 	{
121 		const StrData* pStrData = (const StrData*) rStrColl.At( nIndex );
122 		lcl_GenerateGUID( aGUID, bValidGUID );
123 		if( pStrData )
124 			List::Insert( new XclExpUserBView( pStrData->GetString(), aGUID ), LIST_APPEND );
125 	}
126 }
127 
~XclExpUserBViewList()128 XclExpUserBViewList::~XclExpUserBViewList()
129 {
130 	for( XclExpUserBView* pRec = _First(); pRec; pRec = _Next() )
131 		delete pRec;
132 }
133 
Save(XclExpStream & rStrm)134 void XclExpUserBViewList::Save( XclExpStream& rStrm )
135 {
136 	for( XclExpUserBView* pRec = _First(); pRec; pRec = _Next() )
137 		pRec->Save( rStrm );
138 }
139 
140 //___________________________________________________________________
141 
XclExpUsersViewBegin(const sal_uInt8 * pGUID,sal_uInt32 nTab)142 XclExpUsersViewBegin::XclExpUsersViewBegin( const sal_uInt8* pGUID, sal_uInt32 nTab ) :
143 	nCurrTab( nTab )
144 {
145 	memcpy( aGUID, pGUID, 16 );
146 }
147 
SaveCont(XclExpStream & rStrm)148 void XclExpUsersViewBegin::SaveCont( XclExpStream& rStrm )
149 {
150 	lcl_WriteGUID( rStrm, aGUID );
151 	rStrm	<< nCurrTab
152 			<< (sal_uInt32)	100
153 			<< (sal_uInt32)	64
154 			<< (sal_uInt32)	3
155 			<< (sal_uInt32)	0x0000003C
156 			<< (sal_uInt16)	0
157 			<< (sal_uInt16)	3
158 			<< (sal_uInt16)	0
159 			<< (sal_uInt16)	3
160 			<< (double)		0
161 			<< (double)		0
162 			<< (sal_Int16)	-1
163 			<< (sal_Int16)	-1;
164 }
165 
GetNum() const166 sal_uInt16 XclExpUsersViewBegin::GetNum() const
167 {
168 	return 0x01AA;
169 }
170 
GetLen() const171 sal_Size XclExpUsersViewBegin::GetLen() const
172 {
173 	return 64;
174 }
175 
176 //___________________________________________________________________
177 
SaveCont(XclExpStream & rStrm)178 void XclExpUsersViewEnd::SaveCont( XclExpStream& rStrm )
179 {
180 	rStrm << (sal_uInt16) 0x0001;
181 }
182 
GetNum() const183 sal_uInt16 XclExpUsersViewEnd::GetNum() const
184 {
185 	return 0x01AB;
186 }
187 
GetLen() const188 sal_Size XclExpUsersViewEnd::GetLen() const
189 {
190 	return 2;
191 }
192 
193 //___________________________________________________________________
194 
SaveCont(XclExpStream & rStrm)195 void XclExpChTr0x0191::SaveCont( XclExpStream& rStrm )
196 {
197 	rStrm << (sal_uInt16) 0x0000;
198 }
199 
GetNum() const200 sal_uInt16 XclExpChTr0x0191::GetNum() const
201 {
202 	return 0x0191;
203 }
204 
GetLen() const205 sal_Size XclExpChTr0x0191::GetLen() const
206 {
207 	return 2;
208 }
209 
210 //___________________________________________________________________
211 
SaveCont(XclExpStream & rStrm)212 void XclExpChTr0x0198::SaveCont( XclExpStream& rStrm )
213 {
214 	rStrm	<< (sal_uInt16) 0x0006
215 			<< (sal_uInt16) 0x0000;
216 }
217 
GetNum() const218 sal_uInt16 XclExpChTr0x0198::GetNum() const
219 {
220 	return 0x0198;
221 }
222 
GetLen() const223 sal_Size XclExpChTr0x0198::GetLen() const
224 {
225 	return 4;
226 }
227 
228 //___________________________________________________________________
229 
SaveCont(XclExpStream & rStrm)230 void XclExpChTr0x0192::SaveCont( XclExpStream& rStrm )
231 {
232     rStrm << sal_uInt16( 0x0022 );
233     rStrm.WriteZeroBytes( 510 );
234 }
235 
GetNum() const236 sal_uInt16 XclExpChTr0x0192::GetNum() const
237 {
238 	return 0x0192;
239 }
240 
GetLen() const241 sal_Size XclExpChTr0x0192::GetLen() const
242 {
243 	return 512;
244 }
245 
246 //___________________________________________________________________
247 
SaveCont(XclExpStream & rStrm)248 void XclExpChTr0x0197::SaveCont( XclExpStream& rStrm )
249 {
250 	rStrm << (sal_uInt16) 0x0000;
251 }
252 
GetNum() const253 sal_uInt16 XclExpChTr0x0197::GetNum() const
254 {
255 	return 0x0197;
256 }
257 
GetLen() const258 sal_Size XclExpChTr0x0197::GetLen() const
259 {
260 	return 2;
261 }
262 
263 //___________________________________________________________________
264 
~XclExpChTrEmpty()265 XclExpChTrEmpty::~XclExpChTrEmpty()
266 {
267 }
268 
GetNum() const269 sal_uInt16 XclExpChTrEmpty::GetNum() const
270 {
271 	return nRecNum;
272 }
273 
GetLen() const274 sal_Size XclExpChTrEmpty::GetLen() const
275 {
276 	return 0;
277 }
278 
279 //___________________________________________________________________
280 
~XclExpChTr0x0195()281 XclExpChTr0x0195::~XclExpChTr0x0195()
282 {
283 }
284 
SaveCont(XclExpStream & rStrm)285 void XclExpChTr0x0195::SaveCont( XclExpStream& rStrm )
286 {
287     rStrm.WriteZeroBytes( 162 );
288 }
289 
GetNum() const290 sal_uInt16 XclExpChTr0x0195::GetNum() const
291 {
292 	return 0x0195;
293 }
294 
GetLen() const295 sal_Size XclExpChTr0x0195::GetLen() const
296 {
297 	return 162;
298 }
299 
300 //___________________________________________________________________
301 
~XclExpChTr0x0194()302 XclExpChTr0x0194::~XclExpChTr0x0194()
303 {
304 }
305 
SaveCont(XclExpStream & rStrm)306 void XclExpChTr0x0194::SaveCont( XclExpStream& rStrm )
307 {
308 	rStrm << (sal_uInt32) 0;
309 	lcl_WriteDateTime( rStrm, aDateTime );
310 	rStrm << (sal_uInt8) 0;
311 	lcl_WriteFixedString( rStrm, sUsername, 147 );
312 }
313 
GetNum() const314 sal_uInt16 XclExpChTr0x0194::GetNum() const
315 {
316 	return 0x0194;
317 }
318 
GetLen() const319 sal_Size XclExpChTr0x0194::GetLen() const
320 {
321 	return 162;
322 }
323 
324 //___________________________________________________________________
325 
~XclExpChTrHeader()326 XclExpChTrHeader::~XclExpChTrHeader()
327 {
328 }
329 
SaveCont(XclExpStream & rStrm)330 void XclExpChTrHeader::SaveCont( XclExpStream& rStrm )
331 {
332 	rStrm	<< (sal_uInt16) 0x0006
333 			<< (sal_uInt16) 0x0000
334 			<< (sal_uInt16) 0x000D;
335 	lcl_WriteGUID( rStrm, aGUID );
336 	lcl_WriteGUID( rStrm, aGUID );
337 	rStrm	<< nCount
338 			<< (sal_uInt16) 0x0001
339 			<< (sal_uInt32) 0x00000000
340 			<< (sal_uInt16) 0x001E;
341 }
342 
GetNum() const343 sal_uInt16 XclExpChTrHeader::GetNum() const
344 {
345 	return 0x0196;
346 }
347 
GetLen() const348 sal_Size XclExpChTrHeader::GetLen() const
349 {
350 	return 50;
351 }
352 
353 //___________________________________________________________________
354 
~XclExpChTrInfo()355 XclExpChTrInfo::~XclExpChTrInfo()
356 {
357 }
358 
SaveCont(XclExpStream & rStrm)359 void XclExpChTrInfo::SaveCont( XclExpStream& rStrm )
360 {
361 	rStrm	<< (sal_uInt32)	0xFFFFFFFF
362 			<< (sal_uInt32)	0x00000000
363 			<< (sal_uInt32)	0x00000020
364 			<< (sal_uInt16)	0xFFFF;
365 	lcl_WriteGUID( rStrm, aGUID );
366 	rStrm	<< (sal_uInt16)	0x04B0;
367 	lcl_WriteFixedString( rStrm, sUsername, 113 );
368 	lcl_WriteDateTime( rStrm, aDateTime );
369 	rStrm	<< (sal_uInt8)	0x0000
370 			<< (sal_uInt16)	0x0002;
371 }
372 
GetNum() const373 sal_uInt16 XclExpChTrInfo::GetNum() const
374 {
375 	return 0x0138;
376 }
377 
GetLen() const378 sal_Size XclExpChTrInfo::GetLen() const
379 {
380 	return 158;
381 }
382 
383 //___________________________________________________________________
384 
XclExpChTrTabIdBuffer(sal_uInt16 nCount)385 XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( sal_uInt16 nCount ) :
386 	nBufSize( nCount ),
387 	nLastId( nCount )
388 {
389 	pBuffer = new sal_uInt16[ nBufSize ];
390 	memset( pBuffer, 0, sizeof(sal_uInt16) * nBufSize );
391 	pLast = pBuffer + nBufSize - 1;
392 }
393 
XclExpChTrTabIdBuffer(const XclExpChTrTabIdBuffer & rCopy)394 XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( const XclExpChTrTabIdBuffer& rCopy ) :
395 	nBufSize( rCopy.nBufSize ),
396 	nLastId( rCopy.nLastId )
397 {
398 	pBuffer = new sal_uInt16[ nBufSize ];
399 	memcpy( pBuffer, rCopy.pBuffer, sizeof(sal_uInt16) * nBufSize );
400 	pLast = pBuffer + nBufSize - 1;
401 }
402 
~XclExpChTrTabIdBuffer()403 XclExpChTrTabIdBuffer::~XclExpChTrTabIdBuffer()
404 {
405 	delete[] pBuffer;
406 }
407 
InitFill(sal_uInt16 nIndex)408 void XclExpChTrTabIdBuffer::InitFill( sal_uInt16 nIndex )
409 {
410 	DBG_ASSERT( nIndex < nLastId, "XclExpChTrTabIdBuffer::Insert - out of range" );
411 
412 	sal_uInt16 nFreeCount = 0;
413 	for( sal_uInt16* pElem = pBuffer; pElem <= pLast; pElem++ )
414 	{
415 		if( !*pElem )
416 			nFreeCount++;
417 		if( nFreeCount > nIndex )
418 		{
419 			*pElem = nLastId--;
420 			return;
421 		}
422 	}
423 }
424 
InitFillup()425 void XclExpChTrTabIdBuffer::InitFillup()
426 {
427 	sal_uInt16 nFreeCount = 1;
428 	for( sal_uInt16* pElem = pBuffer; pElem <= pLast; pElem++ )
429 		if( !*pElem )
430 			*pElem = nFreeCount++;
431 	nLastId = nBufSize;
432 }
433 
GetId(sal_uInt16 nIndex) const434 sal_uInt16 XclExpChTrTabIdBuffer::GetId( sal_uInt16 nIndex ) const
435 {
436 	DBG_ASSERT( nIndex < nBufSize, "XclExpChTrTabIdBuffer::GetId - out of range" );
437 	return pBuffer[ nIndex ];
438 }
439 
Remove()440 void XclExpChTrTabIdBuffer::Remove()
441 {
442 	DBG_ASSERT( pBuffer <= pLast, "XclExpChTrTabIdBuffer::Remove - buffer empty" );
443 	sal_uInt16* pElem = pBuffer;
444 	while( (pElem <= pLast) && (*pElem != nLastId) )
445 		pElem++;
446 	while( pElem < pLast )
447 	{
448 		*pElem = *(pElem + 1);
449 		pElem++;
450 	}
451 	pLast--;
452 	nLastId--;
453 }
454 
455 //___________________________________________________________________
456 
~XclExpChTrTabIdBufferList()457 XclExpChTrTabIdBufferList::~XclExpChTrTabIdBufferList()
458 {
459 	for( XclExpChTrTabIdBuffer* pBuffer = First(); pBuffer; pBuffer = Next() )
460 		delete pBuffer;
461 }
462 
463 //___________________________________________________________________
464 
XclExpChTrTabId(const XclExpChTrTabIdBuffer & rBuffer)465 XclExpChTrTabId::XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer ) :
466 	nTabCount( rBuffer.GetBufferCount() )
467 {
468 	pBuffer = new sal_uInt16[ nTabCount ];
469 	rBuffer.GetBufferCopy( pBuffer );
470 }
471 
~XclExpChTrTabId()472 XclExpChTrTabId::~XclExpChTrTabId()
473 {
474 	Clear();
475 }
476 
Copy(const XclExpChTrTabIdBuffer & rBuffer)477 void XclExpChTrTabId::Copy( const XclExpChTrTabIdBuffer& rBuffer )
478 {
479 	Clear();
480 	nTabCount = rBuffer.GetBufferCount();
481 	pBuffer = new sal_uInt16[ nTabCount ];
482 	rBuffer.GetBufferCopy( pBuffer );
483 }
484 
SaveCont(XclExpStream & rStrm)485 void XclExpChTrTabId::SaveCont( XclExpStream& rStrm )
486 {
487     rStrm.EnableEncryption();
488 	if( pBuffer )
489 		for( sal_uInt16* pElem = pBuffer; pElem < (pBuffer + nTabCount); pElem++ )
490 			rStrm << *pElem;
491 	else
492 		for( sal_uInt16 nIndex = 1; nIndex <= nTabCount; nIndex++ )
493 			rStrm << nIndex;
494 }
495 
GetNum() const496 sal_uInt16 XclExpChTrTabId::GetNum() const
497 {
498 	return 0x013D;
499 }
500 
GetLen() const501 sal_Size XclExpChTrTabId::GetLen() const
502 {
503 	return nTabCount << 1;
504 }
505 
506 //___________________________________________________________________
507 
508 // ! does not copy additional actions
XclExpChTrAction(const XclExpChTrAction & rCopy)509 XclExpChTrAction::XclExpChTrAction( const XclExpChTrAction& rCopy ) :
510     ExcRecord( rCopy ),
511 	sUsername( rCopy.sUsername ),
512 	aDateTime( rCopy.aDateTime ),
513 	nIndex( 0 ),
514     pAddAction( 0 ),
515     bAccepted( rCopy.bAccepted ),
516     rTabInfo( rCopy.rTabInfo ),
517 	rIdBuffer( rCopy.rIdBuffer ),
518 	nLength( rCopy.nLength ),
519     nOpCode( rCopy.nOpCode ),
520     bForceInfo( rCopy.bForceInfo )
521 {
522 }
523 
XclExpChTrAction(const ScChangeAction & rAction,const XclExpRoot & rRoot,const XclExpChTrTabIdBuffer & rTabIdBuffer,sal_uInt16 nNewOpCode)524 XclExpChTrAction::XclExpChTrAction(
525 		const ScChangeAction& rAction,
526         const XclExpRoot& rRoot,
527 		const XclExpChTrTabIdBuffer& rTabIdBuffer,
528 		sal_uInt16 nNewOpCode ) :
529 	sUsername( rAction.GetUser() ),
530 	aDateTime( rAction.GetDateTime() ),
531 	nIndex( 0 ),
532 	pAddAction( NULL ),
533 	bAccepted( rAction.IsAccepted() ),
534     rTabInfo( rRoot.GetTabInfo() ),
535 	rIdBuffer( rTabIdBuffer ),
536 	nLength( 0 ),
537 	nOpCode( nNewOpCode ),
538 	bForceInfo( sal_False )
539 {
540 	aDateTime.SetSec( 0 );
541 	aDateTime.Set100Sec( 0 );
542 }
543 
~XclExpChTrAction()544 XclExpChTrAction::~XclExpChTrAction()
545 {
546 	if( pAddAction )
547 		delete pAddAction;
548 }
549 
SetAddAction(XclExpChTrAction * pAction)550 void XclExpChTrAction::SetAddAction( XclExpChTrAction* pAction )
551 {
552 	if( pAddAction )
553 		pAddAction->SetAddAction( pAction );
554 	else
555 		pAddAction = pAction;
556 }
557 
AddDependentContents(const ScChangeAction & rAction,const XclExpRoot & rRoot,ScChangeTrack & rChangeTrack)558 void XclExpChTrAction::AddDependentContents(
559 		const ScChangeAction& rAction,
560         const XclExpRoot& rRoot,
561 		ScChangeTrack& rChangeTrack )
562 {
563 	ScChangeActionTable aActionTable;
564 	rChangeTrack.GetDependents( (ScChangeAction*)(&rAction), aActionTable );
565 	for( const ScChangeAction* pDepAction = aActionTable.First(); pDepAction; pDepAction = aActionTable.Next() )
566 		if( pDepAction->GetType() == SC_CAT_CONTENT )
567 			SetAddAction( new XclExpChTrCellContent(
568                 *((const ScChangeActionContent*) pDepAction), rRoot, rIdBuffer ) );
569 }
570 
SetIndex(sal_uInt32 & rIndex)571 void XclExpChTrAction::SetIndex( sal_uInt32& rIndex )
572 {
573 	nIndex = rIndex++;
574 }
575 
SaveCont(XclExpStream & rStrm)576 void XclExpChTrAction::SaveCont( XclExpStream& rStrm )
577 {
578 	DBG_ASSERT( nOpCode != EXC_CHTR_OP_UNKNOWN, "XclExpChTrAction::SaveCont - unknown action" );
579 	rStrm	<< nLength
580 			<< nIndex
581 			<< nOpCode
582 			<< (sal_uInt16)(bAccepted ? EXC_CHTR_ACCEPT : EXC_CHTR_NOTHING);
583 	SaveActionData( rStrm );
584 }
585 
PrepareSaveAction(XclExpStream &) const586 void XclExpChTrAction::PrepareSaveAction( XclExpStream& /*rStrm*/ ) const
587 {
588 }
589 
CompleteSaveAction(XclExpStream &) const590 void XclExpChTrAction::CompleteSaveAction( XclExpStream& /*rStrm*/ ) const
591 {
592 }
593 
Save(XclExpStream & rStrm)594 void XclExpChTrAction::Save( XclExpStream& rStrm )
595 {
596 	PrepareSaveAction( rStrm );
597 	ExcRecord::Save( rStrm );
598 	if( pAddAction )
599 		pAddAction->Save( rStrm );
600 	CompleteSaveAction( rStrm );
601 }
602 
GetLen() const603 sal_Size XclExpChTrAction::GetLen() const
604 {
605 	return GetHeaderByteCount() + GetActionByteCount();
606 }
607 
608 //___________________________________________________________________
609 
XclExpChTrData()610 XclExpChTrData::XclExpChTrData() :
611     pString( NULL ),
612     fValue( 0.0 ),
613     nRKValue( 0 ),
614     nType( EXC_CHTR_TYPE_EMPTY ),
615     nSize( 0 )
616 {
617 }
618 
~XclExpChTrData()619 XclExpChTrData::~XclExpChTrData()
620 {
621     Clear();
622 }
623 
Clear()624 void XclExpChTrData::Clear()
625 {
626     DELETEZ( pString );
627     mxTokArr.reset();
628     maRefLog.clear();
629 	fValue = 0.0;
630 	nRKValue = 0;
631 	nType = EXC_CHTR_TYPE_EMPTY;
632     nSize = 0;
633 }
634 
WriteFormula(XclExpStream & rStrm,const XclExpChTrTabIdBuffer & rTabIdBuffer)635 void XclExpChTrData::WriteFormula( XclExpStream& rStrm, const XclExpChTrTabIdBuffer& rTabIdBuffer )
636 {
637     DBG_ASSERT( mxTokArr.is() && !mxTokArr->Empty(), "XclExpChTrData::Write - no formula" );
638     rStrm << *mxTokArr;
639 
640     for( XclExpRefLog::const_iterator aIt = maRefLog.begin(), aEnd = maRefLog.end(); aIt != aEnd; ++aIt )
641     {
642         if( aIt->mpUrl && aIt->mpFirstTab )
643         {
644             rStrm << *aIt->mpUrl << (sal_uInt8) 0x01 << *aIt->mpFirstTab << (sal_uInt8) 0x02;
645         }
646 		else
647 		{
648             bool bSingleTab = aIt->mnFirstXclTab == aIt->mnLastXclTab;
649             rStrm.SetSliceSize( bSingleTab ? 6 : 8 );
650             rStrm << (sal_uInt8) 0x01 << (sal_uInt8) 0x02 << (sal_uInt8) 0x00;
651             rStrm << rTabIdBuffer.GetId( aIt->mnFirstXclTab );
652             if( bSingleTab )
653 				rStrm << (sal_uInt8) 0x02;
654 			else
655                 rStrm << (sal_uInt8) 0x00 << rTabIdBuffer.GetId( aIt->mnLastXclTab );
656 		}
657 	}
658     rStrm.SetSliceSize( 0 );
659 	rStrm << (sal_uInt8) 0x00;
660 }
661 
Write(XclExpStream & rStrm,const XclExpChTrTabIdBuffer & rTabIdBuffer)662 void XclExpChTrData::Write( XclExpStream& rStrm, const XclExpChTrTabIdBuffer& rTabIdBuffer )
663 {
664 	switch( nType )
665 	{
666 		case EXC_CHTR_TYPE_RK:
667 			rStrm << nRKValue;
668 		break;
669 		case EXC_CHTR_TYPE_DOUBLE:
670 			rStrm << fValue;
671 		break;
672 		case EXC_CHTR_TYPE_STRING:
673 			DBG_ASSERT( pString, "XclExpChTrData::Write - no string" );
674             rStrm << *pString;
675 		break;
676 		case EXC_CHTR_TYPE_FORMULA:
677             WriteFormula( rStrm, rTabIdBuffer );
678 		break;
679 	}
680 }
681 
682 //___________________________________________________________________
683 
XclExpChTrCellContent(const ScChangeActionContent & rAction,const XclExpRoot & rRoot,const XclExpChTrTabIdBuffer & rTabIdBuffer)684 XclExpChTrCellContent::XclExpChTrCellContent(
685 		const ScChangeActionContent& rAction,
686         const XclExpRoot& rRoot,
687 		const XclExpChTrTabIdBuffer& rTabIdBuffer ) :
688     XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_CELL ),
689     XclExpRoot( rRoot ),
690     pOldData( 0 ),
691     pNewData( 0 ),
692     aPosition( rAction.GetBigRange().MakeRange().aStart )
693 {
694 	sal_uInt32 nDummy32;
695 	sal_uInt16 nDummy16;
696 	GetCellData( rAction.GetOldCell(), pOldData, nDummy32, nOldLength );
697 	GetCellData( rAction.GetNewCell(), pNewData, nLength, nDummy16 );
698 }
699 
~XclExpChTrCellContent()700 XclExpChTrCellContent::~XclExpChTrCellContent()
701 {
702 	if( pOldData )
703 		delete pOldData;
704 	if( pNewData )
705 		delete pNewData;
706 }
707 
MakeEmptyChTrData(XclExpChTrData * & rpData)708 void XclExpChTrCellContent::MakeEmptyChTrData( XclExpChTrData*& rpData )
709 {
710 	if( rpData )
711 		rpData->Clear();
712 	else
713 		rpData = new XclExpChTrData;
714 }
715 
GetCellData(const ScBaseCell * pScCell,XclExpChTrData * & rpData,sal_uInt32 & rXclLength1,sal_uInt16 & rXclLength2)716 void XclExpChTrCellContent::GetCellData(
717 		const ScBaseCell* pScCell,
718 		XclExpChTrData*& rpData,
719 		sal_uInt32& rXclLength1,
720 		sal_uInt16& rXclLength2 )
721 {
722 	MakeEmptyChTrData( rpData );
723 	rXclLength1 = 0x0000003A;
724 	rXclLength2 = 0x0000;
725 
726 	if( !pScCell )
727 	{
728 		delete rpData;
729 		rpData = NULL;
730 		return;
731 	}
732 
733 	switch( pScCell->GetCellType() )
734 	{
735 		case CELLTYPE_VALUE:
736 		{
737 			rpData->fValue = ((const ScValueCell*) pScCell)->GetValue();
738             if( XclTools::GetRKFromDouble( rpData->nRKValue, rpData->fValue ) )
739 			{
740 				rpData->nType = EXC_CHTR_TYPE_RK;
741                 rpData->nSize = 4;
742 				rXclLength1 = 0x0000003E;
743 				rXclLength2 = 0x0004;
744 			}
745 			else
746 			{
747 				rpData->nType = EXC_CHTR_TYPE_DOUBLE;
748                 rpData->nSize = 8;
749 				rXclLength1 = 0x00000042;
750 				rXclLength2 = 0x0008;
751 			}
752 		}
753 		break;
754 		case CELLTYPE_STRING:
755 		case CELLTYPE_EDIT:
756 		{
757 			String sCellStr;
758 			if( pScCell->GetCellType() == CELLTYPE_STRING )
759 				((const ScStringCell*) pScCell)->GetString( sCellStr );
760 			else
761 				((const ScEditCell*) pScCell)->GetString( sCellStr );
762             rpData->pString = new XclExpString( sCellStr, EXC_STR_DEFAULT, 32766 );
763 			rpData->nType = EXC_CHTR_TYPE_STRING;
764             rpData->nSize = 3 + rpData->pString->GetSize();
765 			rXclLength1 = 64 + (sCellStr.Len() << 1);
766 			rXclLength2 = 6 + (sal_uInt16)(sCellStr.Len() << 1);
767 		}
768 		break;
769 		case CELLTYPE_FORMULA:
770 		{
771 			const ScFormulaCell* pFmlCell = (const ScFormulaCell*) pScCell;
772 			const ScTokenArray* pTokenArray = pFmlCell->GetCode();
773 			if( pTokenArray )
774 			{
775                 XclExpRefLog& rRefLog = rpData->maRefLog;
776                 rpData->mxTokArr = GetFormulaCompiler().CreateFormula(
777                     EXC_FMLATYPE_CELL, *pTokenArray, &pFmlCell->aPos, &rRefLog );
778 				rpData->nType = EXC_CHTR_TYPE_FORMULA;
779                 sal_Size nSize = rpData->mxTokArr->GetSize() + 3;
780 
781                 for( XclExpRefLog::const_iterator aIt = rRefLog.begin(), aEnd = rRefLog.end(); aIt != aEnd; ++aIt )
782 				{
783                     if( aIt->mpUrl && aIt->mpFirstTab )
784                         nSize += aIt->mpUrl->GetSize() + aIt->mpFirstTab->GetSize() + 2;
785 					else
786                         nSize += (aIt->mnFirstXclTab == aIt->mnLastXclTab) ? 6 : 8;
787 				}
788                 rpData->nSize = ::std::min< sal_Size >( nSize, 0xFFFF );
789 				rXclLength1 = 0x00000052;
790 				rXclLength2 = 0x0018;
791 			}
792 		}
793 		break;
794         default:;
795 	}
796 }
797 
SaveActionData(XclExpStream & rStrm) const798 void XclExpChTrCellContent::SaveActionData( XclExpStream& rStrm ) const
799 {
800 	WriteTabId( rStrm, aPosition.Tab() );
801 	rStrm	<< (sal_uInt16)((pOldData ? (pOldData->nType << 3) : 0x0000) | (pNewData ? pNewData->nType : 0x0000))
802 			<< (sal_uInt16) 0x0000;
803 	Write2DAddress( rStrm, aPosition );
804 	rStrm	<< nOldLength
805 			<< (sal_uInt32) 0x00000000;
806 	if( pOldData )
807         pOldData->Write( rStrm, rIdBuffer );
808 	if( pNewData )
809         pNewData->Write( rStrm, rIdBuffer );
810 }
811 
GetNum() const812 sal_uInt16 XclExpChTrCellContent::GetNum() const
813 {
814 	return 0x013B;
815 }
816 
GetActionByteCount() const817 sal_Size XclExpChTrCellContent::GetActionByteCount() const
818 {
819     sal_Size nLen = 16;
820 	if( pOldData )
821         nLen += pOldData->nSize;
822 	if( pNewData )
823         nLen += pNewData->nSize;
824 	return nLen;
825 }
826 
827 //___________________________________________________________________
828 
XclExpChTrInsert(const ScChangeAction & rAction,const XclExpRoot & rRoot,const XclExpChTrTabIdBuffer & rTabIdBuffer,ScChangeTrack & rChangeTrack)829 XclExpChTrInsert::XclExpChTrInsert(
830 		const ScChangeAction& rAction,
831         const XclExpRoot& rRoot,
832 		const XclExpChTrTabIdBuffer& rTabIdBuffer,
833 		ScChangeTrack& rChangeTrack ) :
834     XclExpChTrAction( rAction, rRoot, rTabIdBuffer ),
835 	aRange( rAction.GetBigRange().MakeRange() )
836 {
837 	nLength = 0x00000030;
838 	switch( rAction.GetType() )
839 	{
840 		case SC_CAT_INSERT_COLS:	nOpCode = EXC_CHTR_OP_INSCOL;	break;
841 		case SC_CAT_INSERT_ROWS:	nOpCode = EXC_CHTR_OP_INSROW;	break;
842 		case SC_CAT_DELETE_COLS:	nOpCode = EXC_CHTR_OP_DELCOL;	break;
843 		case SC_CAT_DELETE_ROWS:	nOpCode = EXC_CHTR_OP_DELROW;	break;
844 		default:
845 			DBG_ERROR( "XclExpChTrInsert::XclExpChTrInsert - unknown action" );
846 	}
847 
848 	if( nOpCode & EXC_CHTR_OP_COLFLAG )
849 	{
850 		aRange.aStart.SetRow( 0 );
851         aRange.aEnd.SetRow( rRoot.GetXclMaxPos().Row() );
852 	}
853 	else
854 	{
855 		aRange.aStart.SetCol( 0 );
856         aRange.aEnd.SetCol( rRoot.GetXclMaxPos().Col() );
857 	}
858 
859 	if( nOpCode & EXC_CHTR_OP_DELFLAG )
860 	{
861 		SetAddAction( new XclExpChTr0x014A( *this ) );
862         AddDependentContents( rAction, rRoot, rChangeTrack );
863 	}
864 }
865 
~XclExpChTrInsert()866 XclExpChTrInsert::~XclExpChTrInsert()
867 {
868 }
869 
SaveActionData(XclExpStream & rStrm) const870 void XclExpChTrInsert::SaveActionData( XclExpStream& rStrm ) const
871 {
872 	WriteTabId( rStrm, aRange.aStart.Tab() );
873 	rStrm	<< (sal_uInt16)	0x0000;
874 	Write2DRange( rStrm, aRange );
875 	rStrm	<< (sal_uInt32) 0x00000000;
876 }
877 
PrepareSaveAction(XclExpStream & rStrm) const878 void XclExpChTrInsert::PrepareSaveAction( XclExpStream& rStrm ) const
879 {
880 	if( (nOpCode == EXC_CHTR_OP_DELROW) || (nOpCode == EXC_CHTR_OP_DELCOL) )
881 		XclExpChTrEmpty( 0x0150 ).Save( rStrm );
882 }
883 
CompleteSaveAction(XclExpStream & rStrm) const884 void XclExpChTrInsert::CompleteSaveAction( XclExpStream& rStrm ) const
885 {
886 	if( (nOpCode == EXC_CHTR_OP_DELROW) || (nOpCode == EXC_CHTR_OP_DELCOL) )
887 		XclExpChTrEmpty( 0x0151 ).Save( rStrm );
888 }
889 
GetNum() const890 sal_uInt16 XclExpChTrInsert::GetNum() const
891 {
892 	return 0x0137;
893 }
894 
GetActionByteCount() const895 sal_Size XclExpChTrInsert::GetActionByteCount() const
896 {
897 	return 16;
898 }
899 
900 //___________________________________________________________________
901 
XclExpChTrInsertTab(const ScChangeAction & rAction,const XclExpRoot & rRoot,const XclExpChTrTabIdBuffer & rTabIdBuffer)902 XclExpChTrInsertTab::XclExpChTrInsertTab(
903 		const ScChangeAction& rAction,
904         const XclExpRoot& rRoot,
905 		const XclExpChTrTabIdBuffer& rTabIdBuffer ) :
906     XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_INSTAB ),
907     XclExpRoot( rRoot ),
908 	nTab( (SCTAB) rAction.GetBigRange().aStart.Tab() )
909 {
910 	nLength = 0x0000021C;
911 	bForceInfo = sal_True;
912 }
913 
~XclExpChTrInsertTab()914 XclExpChTrInsertTab::~XclExpChTrInsertTab()
915 {
916 }
917 
SaveActionData(XclExpStream & rStrm) const918 void XclExpChTrInsertTab::SaveActionData( XclExpStream& rStrm ) const
919 {
920 	WriteTabId( rStrm, nTab );
921     rStrm << sal_uInt32( 0 );
922     lcl_WriteFixedString( rStrm, XclExpString( GetTabInfo().GetScTabName( nTab ) ), 127 );
923 	lcl_WriteDateTime( rStrm, GetDateTime() );
924     rStrm.WriteZeroBytes( 133 );
925 }
926 
GetNum() const927 sal_uInt16 XclExpChTrInsertTab::GetNum() const
928 {
929 	return 0x014D;
930 }
931 
GetActionByteCount() const932 sal_Size XclExpChTrInsertTab::GetActionByteCount() const
933 {
934 	return 276;
935 }
936 
937 //___________________________________________________________________
938 
XclExpChTrMoveRange(const ScChangeActionMove & rAction,const XclExpRoot & rRoot,const XclExpChTrTabIdBuffer & rTabIdBuffer,ScChangeTrack & rChangeTrack)939 XclExpChTrMoveRange::XclExpChTrMoveRange(
940 		const ScChangeActionMove& rAction,
941         const XclExpRoot& rRoot,
942 		const XclExpChTrTabIdBuffer& rTabIdBuffer,
943 		ScChangeTrack& rChangeTrack ) :
944     XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_MOVE ),
945 	aDestRange( rAction.GetBigRange().MakeRange() )
946 {
947 	nLength = 0x00000042;
948 	aSourceRange = aDestRange;
949 	sal_Int32 nDCols, nDRows, nDTabs;
950 	rAction.GetDelta( nDCols, nDRows, nDTabs );
951 	aSourceRange.aStart.IncRow( (SCROW) -nDRows );
952 	aSourceRange.aStart.IncCol( (SCCOL) -nDCols );
953 	aSourceRange.aStart.IncTab( (SCTAB) -nDTabs );
954 	aSourceRange.aEnd.IncRow( (SCROW) -nDRows );
955 	aSourceRange.aEnd.IncCol( (SCCOL) -nDCols );
956 	aSourceRange.aEnd.IncTab( (SCTAB) -nDTabs );
957     AddDependentContents( rAction, rRoot, rChangeTrack );
958 }
959 
~XclExpChTrMoveRange()960 XclExpChTrMoveRange::~XclExpChTrMoveRange()
961 {
962 }
963 
SaveActionData(XclExpStream & rStrm) const964 void XclExpChTrMoveRange::SaveActionData( XclExpStream& rStrm ) const
965 {
966 	WriteTabId( rStrm, aDestRange.aStart.Tab() );
967 	Write2DRange( rStrm, aSourceRange );
968 	Write2DRange( rStrm, aDestRange );
969 	WriteTabId( rStrm, aSourceRange.aStart.Tab() );
970 	rStrm << (sal_uInt32) 0x00000000;
971 }
972 
PrepareSaveAction(XclExpStream & rStrm) const973 void XclExpChTrMoveRange::PrepareSaveAction( XclExpStream& rStrm ) const
974 {
975 	XclExpChTrEmpty( 0x014E ).Save( rStrm );
976 }
977 
CompleteSaveAction(XclExpStream & rStrm) const978 void XclExpChTrMoveRange::CompleteSaveAction( XclExpStream& rStrm ) const
979 {
980 	XclExpChTrEmpty( 0x014F ).Save( rStrm );
981 }
982 
GetNum() const983 sal_uInt16 XclExpChTrMoveRange::GetNum() const
984 {
985 	return 0x0140;
986 }
987 
GetActionByteCount() const988 sal_Size XclExpChTrMoveRange::GetActionByteCount() const
989 {
990 	return 24;
991 }
992 
993 //___________________________________________________________________
994 
XclExpChTr0x014A(const XclExpChTrInsert & rAction)995 XclExpChTr0x014A::XclExpChTr0x014A( const XclExpChTrInsert& rAction ) :
996 	XclExpChTrInsert( rAction )
997 {
998 	nLength = 0x00000026;
999 	nOpCode = EXC_CHTR_OP_FORMAT;
1000 }
1001 
~XclExpChTr0x014A()1002 XclExpChTr0x014A::~XclExpChTr0x014A()
1003 {
1004 }
1005 
SaveActionData(XclExpStream & rStrm) const1006 void XclExpChTr0x014A::SaveActionData( XclExpStream& rStrm ) const
1007 {
1008 	WriteTabId( rStrm, aRange.aStart.Tab() );
1009 	rStrm	<< (sal_uInt16)	0x0003
1010 			<< (sal_uInt16) 0x0001;
1011 	Write2DRange( rStrm, aRange );
1012 }
1013 
GetNum() const1014 sal_uInt16 XclExpChTr0x014A::GetNum() const
1015 {
1016 	return 0x014A;
1017 }
1018 
GetActionByteCount() const1019 sal_Size XclExpChTr0x014A::GetActionByteCount() const
1020 {
1021 	return 14;
1022 }
1023 
1024 //___________________________________________________________________
1025 
~XclExpChTrActionStack()1026 XclExpChTrActionStack::~XclExpChTrActionStack()
1027 {
1028 	while( XclExpChTrAction* pRec = Pop() )
1029 		delete pRec;
1030 }
1031 
Push(XclExpChTrAction * pNewRec)1032 void XclExpChTrActionStack::Push( XclExpChTrAction* pNewRec )
1033 {
1034 	DBG_ASSERT( pNewRec, "XclExpChTrActionStack::Push - NULL pointer" );
1035 	if( pNewRec )
1036 		Stack::Push( pNewRec );
1037 }
1038 
1039 //___________________________________________________________________
1040 
~XclExpChTrRecordList()1041 XclExpChTrRecordList::~XclExpChTrRecordList()
1042 {
1043 	for( ExcRecord* pRec = First(); pRec; pRec = Next() )
1044 		delete pRec;
1045 }
1046 
Append(ExcRecord * pNewRec)1047 void XclExpChTrRecordList::Append( ExcRecord* pNewRec )
1048 {
1049 	DBG_ASSERT( pNewRec, "XclExpChTrRecordList::Append - NULL pointer" );
1050 	if( pNewRec )
1051 		List::Insert( pNewRec, LIST_APPEND );
1052 }
1053 
Save(XclExpStream & rStrm)1054 void XclExpChTrRecordList::Save( XclExpStream& rStrm )
1055 {
1056 	for( ExcRecord* pRec = First(); pRec; pRec = Next() )
1057 		pRec->Save( rStrm );
1058 }
1059 
1060 //___________________________________________________________________
1061 
XclExpChangeTrack(const XclExpRoot & rRoot)1062 XclExpChangeTrack::XclExpChangeTrack( const XclExpRoot& rRoot ) :
1063     XclExpRoot( rRoot ),
1064 	aRecList(),
1065 	aActionStack(),
1066 	aTabIdBufferList(),
1067 	pTabIdBuffer( NULL ),
1068 	pTempDoc( NULL ),
1069 	nNewAction( 1 ),
1070 	pHeader( NULL ),
1071 	bValidGUID( sal_False )
1072 {
1073     DBG_ASSERT( GetOldRoot().pTabId, "XclExpChangeTrack::XclExpChangeTrack - root data incomplete" );
1074     if( !GetOldRoot().pTabId )
1075 		return;
1076 
1077     ScChangeTrack* pTempChangeTrack = CreateTempChangeTrack();
1078 	if (!pTempChangeTrack)
1079 		return;
1080 
1081     pTabIdBuffer = new XclExpChTrTabIdBuffer( GetTabInfo().GetXclTabCount() );
1082 	aTabIdBufferList.Append( pTabIdBuffer );
1083 
1084 	// calculate final table order (tab id list)
1085 	const ScChangeAction* pScAction;
1086 	for( pScAction = pTempChangeTrack->GetLast(); pScAction; pScAction = pScAction->GetPrev() )
1087 	{
1088 		if( pScAction->GetType() == SC_CAT_INSERT_TABS )
1089 		{
1090             SCTAB nScTab = static_cast< SCTAB >( pScAction->GetBigRange().aStart.Tab() );
1091             pTabIdBuffer->InitFill( GetTabInfo().GetXclTab( nScTab ) );
1092 		}
1093 	}
1094 	pTabIdBuffer->InitFillup();
1095     GetOldRoot().pTabId->Copy( *pTabIdBuffer );
1096 
1097 	// get actions in reverse order
1098 	pScAction = pTempChangeTrack->GetLast();
1099 	while( pScAction )
1100 	{
1101 		PushActionRecord( *pScAction );
1102 		const ScChangeAction* pPrevAction = pScAction->GetPrev();
1103 		pTempChangeTrack->Undo( pScAction->GetActionNumber(), pScAction->GetActionNumber() );
1104 		pScAction = pPrevAction;
1105 	}
1106 
1107 	// build record list
1108 	pHeader = new XclExpChTrHeader;
1109 	aRecList.Append( pHeader );
1110 	aRecList.Append( new XclExpChTr0x0195 );
1111 	aRecList.Append( new XclExpChTr0x0194( *pTempChangeTrack ) );
1112 
1113 	String sLastUsername;
1114 	DateTime aLastDateTime;
1115 	sal_uInt32 nIndex = 1;
1116 	while( XclExpChTrAction* pAction = aActionStack.Pop() )
1117 	{
1118 		if(	(nIndex == 1) || pAction->ForceInfoRecord() ||
1119 			(pAction->GetUsername() != sLastUsername) ||
1120 			(pAction->GetDateTime() != aLastDateTime) )
1121 		{
1122 			lcl_GenerateGUID( aGUID, bValidGUID );
1123 			sLastUsername = pAction->GetUsername();
1124 			aLastDateTime = pAction->GetDateTime();
1125 			aRecList.Append( new XclExpChTrInfo( sLastUsername, aLastDateTime, aGUID ) );
1126 			aRecList.Append( new XclExpChTrTabId( pAction->GetTabIdBuffer() ) );
1127 			pHeader->SetGUID( aGUID );
1128 		}
1129 		pAction->SetIndex( nIndex );
1130 		aRecList.Append( pAction );
1131 	}
1132 
1133 	pHeader->SetGUID( aGUID );
1134 	pHeader->SetCount( nIndex - 1 );
1135 	aRecList.Append( new ExcEof );
1136 }
1137 
~XclExpChangeTrack()1138 XclExpChangeTrack::~XclExpChangeTrack()
1139 {
1140 	if( pTempDoc )
1141 		delete pTempDoc;
1142 }
1143 
CreateTempChangeTrack()1144 ScChangeTrack* XclExpChangeTrack::CreateTempChangeTrack()
1145 {
1146 	// get original change track
1147     ScChangeTrack* pOrigChangeTrack = GetDoc().GetChangeTrack();
1148 	DBG_ASSERT( pOrigChangeTrack, "XclExpChangeTrack::CreateTempChangeTrack - no change track data" );
1149 	if( !pOrigChangeTrack )
1150 		return NULL;
1151 
1152 	// create empty document
1153 	pTempDoc = new ScDocument;
1154 	DBG_ASSERT( pTempDoc, "XclExpChangeTrack::CreateTempChangeTrack - no temp document" );
1155 	if( !pTempDoc )
1156 		return NULL;
1157 
1158 	// adjust table count
1159     SCTAB nOrigCount = GetDoc().GetTableCount();
1160 	String sTabName;
1161 	for( sal_Int32 nIndex = 0; nIndex < nOrigCount; nIndex++ )
1162 	{
1163 		pTempDoc->CreateValidTabName( sTabName );
1164 		pTempDoc->InsertTab( SC_TAB_APPEND, sTabName );
1165 	}
1166 	DBG_ASSERT( nOrigCount == pTempDoc->GetTableCount(),
1167 		"XclExpChangeTrack::CreateTempChangeTrack - table count mismatch" );
1168 	if( nOrigCount != pTempDoc->GetTableCount() )
1169 		return NULL;
1170 
1171     return pOrigChangeTrack->Clone(pTempDoc);
1172 }
1173 
PushActionRecord(const ScChangeAction & rAction)1174 void XclExpChangeTrack::PushActionRecord( const ScChangeAction& rAction )
1175 {
1176 	XclExpChTrAction* pXclAction = NULL;
1177     ScChangeTrack* pTempChangeTrack = pTempDoc->GetChangeTrack();
1178 	switch( rAction.GetType() )
1179 	{
1180 		case SC_CAT_CONTENT:
1181             pXclAction = new XclExpChTrCellContent( (const ScChangeActionContent&) rAction, GetRoot(), *pTabIdBuffer );
1182 		break;
1183 		case SC_CAT_INSERT_ROWS:
1184 		case SC_CAT_INSERT_COLS:
1185 		case SC_CAT_DELETE_ROWS:
1186 		case SC_CAT_DELETE_COLS:
1187             if (pTempChangeTrack)
1188                 pXclAction = new XclExpChTrInsert( rAction, GetRoot(), *pTabIdBuffer, *pTempChangeTrack );
1189 		break;
1190 		case SC_CAT_INSERT_TABS:
1191 		{
1192             pXclAction = new XclExpChTrInsertTab( rAction, GetRoot(), *pTabIdBuffer );
1193 			XclExpChTrTabIdBuffer* pNewBuffer = new XclExpChTrTabIdBuffer( *pTabIdBuffer );
1194 			pNewBuffer->Remove();
1195 			aTabIdBufferList.Append( pNewBuffer );
1196 			pTabIdBuffer = pNewBuffer;
1197 		}
1198 		break;
1199 		case SC_CAT_MOVE:
1200             if (pTempChangeTrack)
1201                 pXclAction = new XclExpChTrMoveRange( (const ScChangeActionMove&) rAction, GetRoot(), *pTabIdBuffer, *pTempChangeTrack );
1202 		break;
1203         default:;
1204 	}
1205 	if( pXclAction )
1206 		aActionStack.Push( pXclAction );
1207 }
1208 
WriteUserNamesStream()1209 sal_Bool XclExpChangeTrack::WriteUserNamesStream()
1210 {
1211 	sal_Bool bRet = sal_False;
1212     SotStorageStreamRef xSvStrm = OpenStream( EXC_STREAM_USERNAMES );
1213 	DBG_ASSERT( xSvStrm.Is(), "XclExpChangeTrack::WriteUserNamesStream - no stream" );
1214 	if( xSvStrm.Is() )
1215 	{
1216         XclExpStream aXclStrm( *xSvStrm, GetRoot() );
1217 		XclExpChTr0x0191().Save( aXclStrm );
1218 		XclExpChTr0x0198().Save( aXclStrm );
1219 		XclExpChTr0x0192().Save( aXclStrm );
1220 		XclExpChTr0x0197().Save( aXclStrm );
1221 		xSvStrm->Commit();
1222 		bRet = sal_True;
1223 	}
1224 	return bRet;
1225 }
1226 
Write()1227 void XclExpChangeTrack::Write()
1228 {
1229 	if( !aRecList.Count() )
1230 		return;
1231 
1232 	if( WriteUserNamesStream() )
1233 	{
1234         SotStorageStreamRef xSvStrm = OpenStream( EXC_STREAM_REVLOG );
1235 		DBG_ASSERT( xSvStrm.Is(), "XclExpChangeTrack::Write - no stream" );
1236 		if( xSvStrm.Is() )
1237 		{
1238             XclExpStream aXclStrm( *xSvStrm, GetRoot(), EXC_MAXRECSIZE_BIFF8 + 8 );
1239 			aRecList.Save( aXclStrm );
1240 			xSvStrm->Commit();
1241 		}
1242 	}
1243 }
1244 
1245