Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 :
22 : #include <stdio.h>
23 : #include <sot/storage.hxx>
24 : #include "XclExpChangeTrack.hxx"
25 : #include "xeformula.hxx"
26 : #include "formulacell.hxx"
27 : #include "xcl97rec.hxx"
28 : #include "document.hxx"
29 : #include "editutil.hxx"
30 :
31 : #include <oox/token/tokens.hxx>
32 : #include <rtl/strbuf.hxx>
33 : #include "svl/sharedstring.hxx"
34 :
35 : using namespace oox;
36 :
37 0 : static OString lcl_GuidToOString( sal_uInt8 aGuid[ 16 ] )
38 : {
39 : char sBuf[ 40 ];
40 : snprintf( sBuf, sizeof( sBuf ),
41 : "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
42 0 : aGuid[ 0 ], aGuid[ 1 ], aGuid[ 2 ], aGuid[ 3 ], aGuid[ 4 ], aGuid[ 5 ], aGuid[ 6 ], aGuid[ 7 ],
43 0 : aGuid[ 8 ], aGuid[ 9 ], aGuid[ 10 ], aGuid[ 11 ], aGuid[ 12 ], aGuid[ 13 ], aGuid[ 14 ], aGuid[ 15 ] );
44 0 : return OString( sBuf );
45 : }
46 :
47 0 : static OString lcl_DateTimeToOString( const DateTime& rDateTime )
48 : {
49 : char sBuf[ 200 ];
50 : snprintf( sBuf, sizeof( sBuf ),
51 : "%d-%02d-%02dT%02d:%02d:%02d.%09" SAL_PRIuUINT32 "Z",
52 0 : rDateTime.GetYear(), rDateTime.GetMonth(), rDateTime.GetDay(),
53 0 : rDateTime.GetHour(), rDateTime.GetMin(), rDateTime.GetSec(),
54 0 : rDateTime.GetNanoSec() );
55 0 : return OString( sBuf );
56 : }
57 :
58 :
59 : // local functions
60 :
61 0 : static void lcl_WriteDateTime( XclExpStream& rStrm, const DateTime& rDateTime )
62 : {
63 0 : rStrm.SetSliceSize( 7 );
64 0 : rStrm << (sal_uInt16) rDateTime.GetYear()
65 0 : << (sal_uInt8) rDateTime.GetMonth()
66 0 : << (sal_uInt8) rDateTime.GetDay()
67 0 : << (sal_uInt8) rDateTime.GetHour()
68 0 : << (sal_uInt8) rDateTime.GetMin()
69 0 : << (sal_uInt8) rDateTime.GetSec();
70 0 : rStrm.SetSliceSize( 0 );
71 0 : }
72 :
73 : // write string and fill rest of <nLength> with zero bytes
74 : // <nLength> is without string header
75 0 : static void lcl_WriteFixedString( XclExpStream& rStrm, const XclExpString& rString, sal_Size nLength )
76 : {
77 0 : sal_Size nStrBytes = rString.GetBufferSize();
78 : OSL_ENSURE( nLength >= nStrBytes, "lcl_WriteFixedString - String too long" );
79 0 : if( rString.Len() > 0 )
80 0 : rStrm << rString;
81 0 : if( nLength > nStrBytes )
82 0 : rStrm.WriteZeroBytes( nLength - nStrBytes );
83 0 : }
84 :
85 0 : static inline void lcl_GenerateGUID( sal_uInt8* pGUID, bool& rValidGUID )
86 : {
87 0 : rtl_createUuid( pGUID, rValidGUID ? pGUID : NULL, false );
88 0 : rValidGUID = true;
89 0 : }
90 :
91 0 : static inline void lcl_WriteGUID( XclExpStream& rStrm, const sal_uInt8* pGUID )
92 : {
93 0 : rStrm.SetSliceSize( 16 );
94 0 : for( sal_Size nIndex = 0; nIndex < 16; nIndex++ )
95 0 : rStrm << pGUID[ nIndex ];
96 0 : rStrm.SetSliceSize( 0 );
97 0 : }
98 :
99 0 : XclExpUserBView::XclExpUserBView( const OUString& rUsername, const sal_uInt8* pGUID ) :
100 0 : sUsername( rUsername )
101 : {
102 0 : memcpy( aGUID, pGUID, 16 );
103 0 : }
104 :
105 0 : void XclExpUserBView::SaveCont( XclExpStream& rStrm )
106 : {
107 0 : rStrm << (sal_uInt32) 0xFF078014
108 0 : << (sal_uInt32) 0x00000001;
109 0 : lcl_WriteGUID( rStrm, aGUID );
110 0 : rStrm.WriteZeroBytes( 8 );
111 0 : rStrm << (sal_uInt32) 1200
112 0 : << (sal_uInt32) 1000
113 0 : << (sal_uInt16) 1000
114 0 : << (sal_uInt16) 0x0CF7
115 0 : << (sal_uInt16) 0x0000
116 0 : << (sal_uInt16) 0x0001
117 0 : << (sal_uInt16) 0x0000;
118 0 : if( sUsername.Len() > 0 )
119 0 : rStrm << sUsername;
120 0 : }
121 :
122 0 : sal_uInt16 XclExpUserBView::GetNum() const
123 : {
124 0 : return 0x01A9;
125 : }
126 :
127 0 : sal_Size XclExpUserBView::GetLen() const
128 : {
129 0 : return 50 + ((sUsername.Len() > 0) ? sUsername.GetSize() : 0);
130 : }
131 :
132 0 : XclExpUserBViewList::XclExpUserBViewList( const ScChangeTrack& rChangeTrack )
133 : {
134 : sal_uInt8 aGUID[ 16 ];
135 0 : bool bValidGUID = false;
136 0 : const std::set<OUString>& rStrColl = rChangeTrack.GetUserCollection();
137 0 : aViews.reserve(rStrColl.size());
138 0 : std::set<OUString>::const_iterator it = rStrColl.begin(), itEnd = rStrColl.end();
139 0 : for (; it != itEnd; ++it)
140 : {
141 0 : lcl_GenerateGUID( aGUID, bValidGUID );
142 0 : aViews.push_back( new XclExpUserBView(*it, aGUID) );
143 : }
144 0 : }
145 :
146 0 : XclExpUserBViewList::~XclExpUserBViewList()
147 : {
148 0 : for( iterator iter = aViews.begin(); iter != aViews.end(); ++iter )
149 0 : delete *iter;
150 0 : }
151 :
152 0 : void XclExpUserBViewList::Save( XclExpStream& rStrm )
153 : {
154 0 : for( iterator iter = aViews.begin(); iter != aViews.end(); ++iter )
155 0 : (*iter)->Save( rStrm );
156 0 : }
157 :
158 0 : XclExpUsersViewBegin::XclExpUsersViewBegin( const sal_uInt8* pGUID, sal_uInt32 nTab ) :
159 0 : nCurrTab( nTab )
160 : {
161 0 : memcpy( aGUID, pGUID, 16 );
162 0 : }
163 :
164 0 : void XclExpUsersViewBegin::SaveCont( XclExpStream& rStrm )
165 : {
166 0 : lcl_WriteGUID( rStrm, aGUID );
167 0 : rStrm << nCurrTab
168 0 : << (sal_uInt32) 100
169 0 : << (sal_uInt32) 64
170 0 : << (sal_uInt32) 3
171 0 : << (sal_uInt32) 0x0000003C
172 0 : << (sal_uInt16) 0
173 0 : << (sal_uInt16) 3
174 0 : << (sal_uInt16) 0
175 0 : << (sal_uInt16) 3
176 0 : << (double) 0
177 0 : << (double) 0
178 0 : << (sal_Int16) -1
179 0 : << (sal_Int16) -1;
180 0 : }
181 :
182 0 : sal_uInt16 XclExpUsersViewBegin::GetNum() const
183 : {
184 0 : return 0x01AA;
185 : }
186 :
187 0 : sal_Size XclExpUsersViewBegin::GetLen() const
188 : {
189 0 : return 64;
190 : }
191 :
192 0 : void XclExpUsersViewEnd::SaveCont( XclExpStream& rStrm )
193 : {
194 0 : rStrm << (sal_uInt16) 0x0001;
195 0 : }
196 :
197 0 : sal_uInt16 XclExpUsersViewEnd::GetNum() const
198 : {
199 0 : return 0x01AB;
200 : }
201 :
202 0 : sal_Size XclExpUsersViewEnd::GetLen() const
203 : {
204 0 : return 2;
205 : }
206 :
207 0 : void XclExpChTr0x0191::SaveCont( XclExpStream& rStrm )
208 : {
209 0 : rStrm << (sal_uInt16) 0x0000;
210 0 : }
211 :
212 0 : sal_uInt16 XclExpChTr0x0191::GetNum() const
213 : {
214 0 : return 0x0191;
215 : }
216 :
217 0 : sal_Size XclExpChTr0x0191::GetLen() const
218 : {
219 0 : return 2;
220 : }
221 :
222 0 : void XclExpChTr0x0198::SaveCont( XclExpStream& rStrm )
223 : {
224 0 : rStrm << (sal_uInt16) 0x0006
225 0 : << (sal_uInt16) 0x0000;
226 0 : }
227 :
228 0 : sal_uInt16 XclExpChTr0x0198::GetNum() const
229 : {
230 0 : return 0x0198;
231 : }
232 :
233 0 : sal_Size XclExpChTr0x0198::GetLen() const
234 : {
235 0 : return 4;
236 : }
237 :
238 0 : void XclExpChTr0x0192::SaveCont( XclExpStream& rStrm )
239 : {
240 0 : rStrm << sal_uInt16( 0x0022 );
241 0 : rStrm.WriteZeroBytes( 510 );
242 0 : }
243 :
244 0 : sal_uInt16 XclExpChTr0x0192::GetNum() const
245 : {
246 0 : return 0x0192;
247 : }
248 :
249 0 : sal_Size XclExpChTr0x0192::GetLen() const
250 : {
251 0 : return 512;
252 : }
253 :
254 0 : void XclExpChTr0x0197::SaveCont( XclExpStream& rStrm )
255 : {
256 0 : rStrm << (sal_uInt16) 0x0000;
257 0 : }
258 :
259 0 : sal_uInt16 XclExpChTr0x0197::GetNum() const
260 : {
261 0 : return 0x0197;
262 : }
263 :
264 0 : sal_Size XclExpChTr0x0197::GetLen() const
265 : {
266 0 : return 2;
267 : }
268 :
269 0 : XclExpChTrEmpty::~XclExpChTrEmpty()
270 : {
271 0 : }
272 :
273 0 : sal_uInt16 XclExpChTrEmpty::GetNum() const
274 : {
275 0 : return nRecNum;
276 : }
277 :
278 0 : sal_Size XclExpChTrEmpty::GetLen() const
279 : {
280 0 : return 0;
281 : }
282 :
283 0 : XclExpChTr0x0195::~XclExpChTr0x0195()
284 : {
285 0 : }
286 :
287 0 : void XclExpChTr0x0195::SaveCont( XclExpStream& rStrm )
288 : {
289 0 : rStrm.WriteZeroBytes( 162 );
290 0 : }
291 :
292 0 : sal_uInt16 XclExpChTr0x0195::GetNum() const
293 : {
294 0 : return 0x0195;
295 : }
296 :
297 0 : sal_Size XclExpChTr0x0195::GetLen() const
298 : {
299 0 : return 162;
300 : }
301 :
302 0 : XclExpChTr0x0194::~XclExpChTr0x0194()
303 : {
304 0 : }
305 :
306 0 : void XclExpChTr0x0194::SaveCont( XclExpStream& rStrm )
307 : {
308 0 : rStrm << (sal_uInt32) 0;
309 0 : lcl_WriteDateTime( rStrm, aDateTime );
310 0 : rStrm << (sal_uInt8) 0;
311 0 : lcl_WriteFixedString( rStrm, sUsername, 147 );
312 0 : }
313 :
314 0 : sal_uInt16 XclExpChTr0x0194::GetNum() const
315 : {
316 0 : return 0x0194;
317 : }
318 :
319 0 : sal_Size XclExpChTr0x0194::GetLen() const
320 : {
321 0 : return 162;
322 : }
323 :
324 0 : XclExpChTrHeader::~XclExpChTrHeader()
325 : {
326 0 : }
327 :
328 0 : void XclExpChTrHeader::SaveCont( XclExpStream& rStrm )
329 : {
330 0 : rStrm << (sal_uInt16) 0x0006
331 0 : << (sal_uInt16) 0x0000
332 0 : << (sal_uInt16) 0x000D;
333 0 : lcl_WriteGUID( rStrm, aGUID );
334 0 : lcl_WriteGUID( rStrm, aGUID );
335 0 : rStrm << nCount
336 0 : << (sal_uInt16) 0x0001
337 0 : << (sal_uInt32) 0x00000000
338 0 : << (sal_uInt16) 0x001E;
339 0 : }
340 :
341 0 : sal_uInt16 XclExpChTrHeader::GetNum() const
342 : {
343 0 : return 0x0196;
344 : }
345 :
346 0 : sal_Size XclExpChTrHeader::GetLen() const
347 : {
348 0 : return 50;
349 : }
350 :
351 0 : void XclExpChTrHeader::SaveXml( XclExpXmlStream& rRevisionHeadersStrm )
352 : {
353 0 : sax_fastparser::FSHelperPtr pHeaders = rRevisionHeadersStrm.GetCurrentStream();
354 : rRevisionHeadersStrm.WriteAttributes(
355 : XML_guid, lcl_GuidToOString( aGUID ).getStr(),
356 : XML_lastGuid, NULL, // OOXTODO
357 : XML_shared, NULL, // OOXTODO
358 : XML_diskRevisions, NULL, // OOXTODO
359 : XML_history, NULL, // OOXTODO
360 : XML_trackRevisions, NULL, // OOXTODO
361 : XML_exclusive, NULL, // OOXTODO
362 : XML_revisionId, NULL, // OOXTODO
363 : XML_version, NULL, // OOXTODO
364 : XML_keepChangeHistory, NULL, // OOXTODO
365 : XML_protected, NULL, // OOXTODO
366 : XML_preserveHistory, NULL, // OOXTODO
367 0 : FSEND );
368 0 : pHeaders->write( ">" );
369 0 : }
370 :
371 0 : XclExpChTrInfo::~XclExpChTrInfo()
372 : {
373 0 : }
374 :
375 0 : void XclExpChTrInfo::SaveCont( XclExpStream& rStrm )
376 : {
377 0 : rStrm << (sal_uInt32) 0xFFFFFFFF
378 0 : << (sal_uInt32) 0x00000000
379 0 : << (sal_uInt32) 0x00000020
380 0 : << (sal_uInt16) 0xFFFF;
381 0 : lcl_WriteGUID( rStrm, aGUID );
382 0 : rStrm << (sal_uInt16) 0x04B0;
383 0 : lcl_WriteFixedString( rStrm, sUsername, 113 );
384 0 : lcl_WriteDateTime( rStrm, aDateTime );
385 0 : rStrm << (sal_uInt8) 0x0000
386 0 : << (sal_uInt16) 0x0002;
387 0 : }
388 :
389 0 : sal_uInt16 XclExpChTrInfo::GetNum() const
390 : {
391 0 : return 0x0138;
392 : }
393 :
394 0 : sal_Size XclExpChTrInfo::GetLen() const
395 : {
396 0 : return 158;
397 : }
398 :
399 0 : void XclExpChTrInfo::SaveXml( XclExpXmlStream& rRevisionHeadersStrm )
400 : {
401 0 : sax_fastparser::FSHelperPtr pHeader = rRevisionHeadersStrm.GetCurrentStream();
402 :
403 0 : OUString sRelationshipId;
404 : sax_fastparser::FSHelperPtr pRevisionLog = rRevisionHeadersStrm.CreateOutputStream(
405 : XclXmlUtils::GetStreamName( "xl/revisions/", "revisionLog", mnLogNumber ),
406 : XclXmlUtils::GetStreamName( NULL, "revisionLog", mnLogNumber ),
407 0 : rRevisionHeadersStrm.GetCurrentStream()->getOutputStream(),
408 : "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml",
409 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionLog",
410 0 : &sRelationshipId );
411 :
412 : rRevisionHeadersStrm.WriteAttributes(
413 : XML_guid, lcl_GuidToOString( aGUID ).getStr(),
414 : XML_dateTime, lcl_DateTimeToOString( aDateTime ).getStr(),
415 : XML_maxSheetId, NULL, // OOXTODO
416 : XML_userName, XclXmlUtils::ToOString( sUsername ).getStr(),
417 : FSNS( XML_r, XML_id ), XclXmlUtils::ToOString( sRelationshipId ).getStr(),
418 : XML_minRId, NULL, // OOXTODO
419 : XML_maxRId, NULL, // OOXTODO
420 0 : FSEND );
421 0 : pHeader->write( ">" );
422 :
423 0 : rRevisionHeadersStrm.PushStream( pRevisionLog );
424 0 : }
425 :
426 0 : XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( sal_uInt16 nCount ) :
427 : nBufSize( nCount ),
428 0 : nLastId( nCount )
429 : {
430 0 : pBuffer = new sal_uInt16[ nBufSize ];
431 0 : memset( pBuffer, 0, sizeof(sal_uInt16) * nBufSize );
432 0 : pLast = pBuffer + nBufSize - 1;
433 0 : }
434 :
435 0 : XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( const XclExpChTrTabIdBuffer& rCopy ) :
436 : nBufSize( rCopy.nBufSize ),
437 0 : nLastId( rCopy.nLastId )
438 : {
439 0 : pBuffer = new sal_uInt16[ nBufSize ];
440 0 : memcpy( pBuffer, rCopy.pBuffer, sizeof(sal_uInt16) * nBufSize );
441 0 : pLast = pBuffer + nBufSize - 1;
442 0 : }
443 :
444 0 : XclExpChTrTabIdBuffer::~XclExpChTrTabIdBuffer()
445 : {
446 0 : delete[] pBuffer;
447 0 : }
448 :
449 0 : void XclExpChTrTabIdBuffer::InitFill( sal_uInt16 nIndex )
450 : {
451 : OSL_ENSURE( nIndex < nLastId, "XclExpChTrTabIdBuffer::Insert - out of range" );
452 :
453 0 : sal_uInt16 nFreeCount = 0;
454 0 : for( sal_uInt16* pElem = pBuffer; pElem <= pLast; pElem++ )
455 : {
456 0 : if( !*pElem )
457 0 : nFreeCount++;
458 0 : if( nFreeCount > nIndex )
459 : {
460 0 : *pElem = nLastId--;
461 0 : return;
462 : }
463 : }
464 : }
465 :
466 0 : void XclExpChTrTabIdBuffer::InitFillup()
467 : {
468 0 : sal_uInt16 nFreeCount = 1;
469 0 : for( sal_uInt16* pElem = pBuffer; pElem <= pLast; pElem++ )
470 0 : if( !*pElem )
471 0 : *pElem = nFreeCount++;
472 0 : nLastId = nBufSize;
473 0 : }
474 :
475 0 : sal_uInt16 XclExpChTrTabIdBuffer::GetId( sal_uInt16 nIndex ) const
476 : {
477 : OSL_ENSURE( nIndex < nBufSize, "XclExpChTrTabIdBuffer::GetId - out of range" );
478 0 : return pBuffer[ nIndex ];
479 : }
480 :
481 0 : void XclExpChTrTabIdBuffer::Remove()
482 : {
483 : OSL_ENSURE( pBuffer <= pLast, "XclExpChTrTabIdBuffer::Remove - buffer empty" );
484 0 : sal_uInt16* pElem = pBuffer;
485 0 : while( (pElem <= pLast) && (*pElem != nLastId) )
486 0 : pElem++;
487 0 : while( pElem < pLast )
488 : {
489 0 : *pElem = *(pElem + 1);
490 0 : pElem++;
491 : }
492 0 : pLast--;
493 0 : nLastId--;
494 0 : }
495 :
496 0 : XclExpChTrTabId::XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer, bool bInRevisionHeaders )
497 0 : : nTabCount( rBuffer.GetBufferCount() )
498 0 : , mbInRevisionHeaders( bInRevisionHeaders )
499 : {
500 0 : pBuffer = new sal_uInt16[ nTabCount ];
501 0 : rBuffer.GetBufferCopy( pBuffer );
502 0 : }
503 :
504 0 : XclExpChTrTabId::~XclExpChTrTabId()
505 : {
506 0 : Clear();
507 0 : }
508 :
509 0 : void XclExpChTrTabId::Copy( const XclExpChTrTabIdBuffer& rBuffer )
510 : {
511 0 : Clear();
512 0 : nTabCount = rBuffer.GetBufferCount();
513 0 : pBuffer = new sal_uInt16[ nTabCount ];
514 0 : rBuffer.GetBufferCopy( pBuffer );
515 0 : }
516 :
517 0 : void XclExpChTrTabId::SaveCont( XclExpStream& rStrm )
518 : {
519 0 : rStrm.EnableEncryption();
520 0 : if( pBuffer )
521 0 : for( sal_uInt16* pElem = pBuffer; pElem < (pBuffer + nTabCount); pElem++ )
522 0 : rStrm << *pElem;
523 : else
524 0 : for( sal_uInt16 nIndex = 1; nIndex <= nTabCount; nIndex++ )
525 0 : rStrm << nIndex;
526 0 : }
527 :
528 0 : sal_uInt16 XclExpChTrTabId::GetNum() const
529 : {
530 0 : return 0x013D;
531 : }
532 :
533 0 : sal_Size XclExpChTrTabId::GetLen() const
534 : {
535 0 : return nTabCount << 1;
536 : }
537 :
538 0 : void XclExpChTrTabId::SaveXml( XclExpXmlStream& rRevisionLogStrm )
539 : {
540 0 : if( !mbInRevisionHeaders )
541 0 : return;
542 :
543 0 : sax_fastparser::FSHelperPtr pRevisionLog = rRevisionLogStrm.GetCurrentStream();
544 0 : rRevisionLogStrm.PopStream();
545 :
546 0 : sax_fastparser::FSHelperPtr pHeader = rRevisionLogStrm.GetCurrentStream();
547 : pHeader->startElement( XML_sheetIdMap,
548 : XML_count, OString::number( nTabCount ).getStr(),
549 0 : FSEND );
550 0 : for( int i = 0; i < nTabCount; ++i )
551 : {
552 : pHeader->singleElement( XML_sheetId,
553 0 : XML_val, OString::number( pBuffer[ i ] ).getStr(),
554 0 : FSEND );
555 : }
556 0 : pHeader->endElement( XML_sheetIdMap );
557 :
558 0 : rRevisionLogStrm.PushStream( pRevisionLog );
559 : }
560 :
561 : // ! does not copy additional actions
562 0 : XclExpChTrAction::XclExpChTrAction( const XclExpChTrAction& rCopy ) :
563 : ExcRecord( rCopy ),
564 : sUsername( rCopy.sUsername ),
565 : aDateTime( rCopy.aDateTime ),
566 : nIndex( 0 ),
567 : pAddAction( 0 ),
568 : bAccepted( rCopy.bAccepted ),
569 : rTabInfo( rCopy.rTabInfo ),
570 : rIdBuffer( rCopy.rIdBuffer ),
571 : nLength( rCopy.nLength ),
572 : nOpCode( rCopy.nOpCode ),
573 0 : bForceInfo( rCopy.bForceInfo )
574 : {
575 0 : }
576 :
577 0 : XclExpChTrAction::XclExpChTrAction(
578 : const ScChangeAction& rAction,
579 : const XclExpRoot& rRoot,
580 : const XclExpChTrTabIdBuffer& rTabIdBuffer,
581 : sal_uInt16 nNewOpCode ) :
582 0 : sUsername( rAction.GetUser() ),
583 : aDateTime( rAction.GetDateTime() ),
584 : nIndex( 0 ),
585 : pAddAction( NULL ),
586 0 : bAccepted( rAction.IsAccepted() ),
587 0 : rTabInfo( rRoot.GetTabInfo() ),
588 : rIdBuffer( rTabIdBuffer ),
589 : nLength( 0 ),
590 : nOpCode( nNewOpCode ),
591 0 : bForceInfo( false )
592 : {
593 0 : aDateTime.SetSec( 0 );
594 0 : aDateTime.SetNanoSec( 0 );
595 0 : }
596 :
597 0 : XclExpChTrAction::~XclExpChTrAction()
598 : {
599 0 : if( pAddAction )
600 0 : delete pAddAction;
601 0 : }
602 :
603 0 : void XclExpChTrAction::SetAddAction( XclExpChTrAction* pAction )
604 : {
605 0 : if( pAddAction )
606 0 : pAddAction->SetAddAction( pAction );
607 : else
608 0 : pAddAction = pAction;
609 0 : }
610 :
611 0 : void XclExpChTrAction::AddDependentContents(
612 : const ScChangeAction& rAction,
613 : const XclExpRoot& rRoot,
614 : ScChangeTrack& rChangeTrack )
615 : {
616 0 : ScChangeActionMap aActionMap;
617 0 : ScChangeActionMap::iterator itChangeAction;
618 :
619 0 : rChangeTrack.GetDependents( (ScChangeAction*)(&rAction), aActionMap );
620 0 : for( itChangeAction = aActionMap.begin(); itChangeAction != aActionMap.end(); ++itChangeAction )
621 0 : if( itChangeAction->second->GetType() == SC_CAT_CONTENT )
622 : SetAddAction( new XclExpChTrCellContent(
623 0 : *((const ScChangeActionContent*) itChangeAction->second), rRoot, rIdBuffer ) );
624 0 : }
625 :
626 0 : void XclExpChTrAction::SetIndex( sal_uInt32& rIndex )
627 : {
628 0 : nIndex = rIndex++;
629 0 : }
630 :
631 0 : void XclExpChTrAction::SaveCont( XclExpStream& rStrm )
632 : {
633 : OSL_ENSURE( nOpCode != EXC_CHTR_OP_UNKNOWN, "XclExpChTrAction::SaveCont - unknown action" );
634 0 : rStrm << nLength
635 0 : << nIndex
636 0 : << nOpCode
637 0 : << (sal_uInt16)(bAccepted ? EXC_CHTR_ACCEPT : EXC_CHTR_NOTHING);
638 0 : SaveActionData( rStrm );
639 0 : }
640 :
641 0 : void XclExpChTrAction::PrepareSaveAction( XclExpStream& /*rStrm*/ ) const
642 : {
643 0 : }
644 :
645 0 : void XclExpChTrAction::CompleteSaveAction( XclExpStream& /*rStrm*/ ) const
646 : {
647 0 : }
648 :
649 0 : void XclExpChTrAction::Save( XclExpStream& rStrm )
650 : {
651 0 : PrepareSaveAction( rStrm );
652 0 : ExcRecord::Save( rStrm );
653 0 : if( pAddAction )
654 0 : pAddAction->Save( rStrm );
655 0 : CompleteSaveAction( rStrm );
656 0 : }
657 :
658 0 : sal_Size XclExpChTrAction::GetLen() const
659 : {
660 0 : return GetHeaderByteCount() + GetActionByteCount();
661 : }
662 :
663 0 : XclExpChTrData::XclExpChTrData() :
664 : pString( NULL ),
665 : mpFormulaCell( NULL ),
666 : fValue( 0.0 ),
667 : nRKValue( 0 ),
668 : nType( EXC_CHTR_TYPE_EMPTY ),
669 0 : nSize( 0 )
670 : {
671 0 : }
672 :
673 0 : XclExpChTrData::~XclExpChTrData()
674 : {
675 0 : Clear();
676 0 : }
677 :
678 0 : void XclExpChTrData::Clear()
679 : {
680 0 : DELETEZ( pString );
681 0 : mpFormulaCell = NULL;
682 0 : mxTokArr.reset();
683 0 : maRefLog.clear();
684 0 : fValue = 0.0;
685 0 : nRKValue = 0;
686 0 : nType = EXC_CHTR_TYPE_EMPTY;
687 0 : nSize = 0;
688 0 : }
689 :
690 0 : void XclExpChTrData::WriteFormula( XclExpStream& rStrm, const XclExpChTrTabIdBuffer& rTabIdBuffer )
691 : {
692 : OSL_ENSURE( mxTokArr && !mxTokArr->Empty(), "XclExpChTrData::Write - no formula" );
693 0 : rStrm << *mxTokArr;
694 :
695 0 : for( XclExpRefLog::const_iterator aIt = maRefLog.begin(), aEnd = maRefLog.end(); aIt != aEnd; ++aIt )
696 : {
697 0 : if( aIt->mpUrl && aIt->mpFirstTab )
698 : {
699 0 : rStrm << *aIt->mpUrl << (sal_uInt8) 0x01 << *aIt->mpFirstTab << (sal_uInt8) 0x02;
700 : }
701 : else
702 : {
703 0 : bool bSingleTab = aIt->mnFirstXclTab == aIt->mnLastXclTab;
704 0 : rStrm.SetSliceSize( bSingleTab ? 6 : 8 );
705 0 : rStrm << (sal_uInt8) 0x01 << (sal_uInt8) 0x02 << (sal_uInt8) 0x00;
706 0 : rStrm << rTabIdBuffer.GetId( aIt->mnFirstXclTab );
707 0 : if( bSingleTab )
708 0 : rStrm << (sal_uInt8) 0x02;
709 : else
710 0 : rStrm << (sal_uInt8) 0x00 << rTabIdBuffer.GetId( aIt->mnLastXclTab );
711 : }
712 : }
713 0 : rStrm.SetSliceSize( 0 );
714 0 : rStrm << (sal_uInt8) 0x00;
715 0 : }
716 :
717 0 : void XclExpChTrData::Write( XclExpStream& rStrm, const XclExpChTrTabIdBuffer& rTabIdBuffer )
718 : {
719 0 : switch( nType )
720 : {
721 : case EXC_CHTR_TYPE_RK:
722 0 : rStrm << nRKValue;
723 0 : break;
724 : case EXC_CHTR_TYPE_DOUBLE:
725 0 : rStrm << fValue;
726 0 : break;
727 : case EXC_CHTR_TYPE_STRING:
728 : OSL_ENSURE( pString, "XclExpChTrData::Write - no string" );
729 0 : rStrm << *pString;
730 0 : break;
731 : case EXC_CHTR_TYPE_FORMULA:
732 0 : WriteFormula( rStrm, rTabIdBuffer );
733 0 : break;
734 : }
735 0 : }
736 :
737 0 : XclExpChTrCellContent::XclExpChTrCellContent(
738 : const ScChangeActionContent& rAction,
739 : const XclExpRoot& rRoot,
740 : const XclExpChTrTabIdBuffer& rTabIdBuffer ) :
741 : XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_CELL ),
742 : XclExpRoot( rRoot ),
743 : pOldData( 0 ),
744 : pNewData( 0 ),
745 0 : aPosition( rAction.GetBigRange().MakeRange().aStart )
746 : {
747 : sal_uInt32 nDummy32;
748 : sal_uInt16 nDummy16;
749 0 : GetCellData( rRoot, rAction.GetOldCell(), pOldData, nDummy32, nOldLength );
750 0 : GetCellData( rRoot, rAction.GetNewCell(), pNewData, nLength, nDummy16 );
751 0 : }
752 :
753 0 : XclExpChTrCellContent::~XclExpChTrCellContent()
754 : {
755 0 : if( pOldData )
756 0 : delete pOldData;
757 0 : if( pNewData )
758 0 : delete pNewData;
759 0 : }
760 :
761 0 : void XclExpChTrCellContent::MakeEmptyChTrData( XclExpChTrData*& rpData )
762 : {
763 0 : if( rpData )
764 0 : rpData->Clear();
765 : else
766 0 : rpData = new XclExpChTrData;
767 0 : }
768 :
769 0 : void XclExpChTrCellContent::GetCellData(
770 : const XclExpRoot& rRoot, const ScCellValue& rScCell,
771 : XclExpChTrData*& rpData, sal_uInt32& rXclLength1, sal_uInt16& rXclLength2 )
772 : {
773 0 : MakeEmptyChTrData( rpData );
774 0 : rXclLength1 = 0x0000003A;
775 0 : rXclLength2 = 0x0000;
776 :
777 0 : if (rScCell.isEmpty())
778 : {
779 0 : delete rpData;
780 0 : rpData = NULL;
781 0 : return;
782 : }
783 :
784 0 : switch (rScCell.meType)
785 : {
786 : case CELLTYPE_VALUE:
787 : {
788 0 : rpData->fValue = rScCell.mfValue;
789 0 : if( XclTools::GetRKFromDouble( rpData->nRKValue, rpData->fValue ) )
790 : {
791 0 : rpData->nType = EXC_CHTR_TYPE_RK;
792 0 : rpData->nSize = 4;
793 0 : rXclLength1 = 0x0000003E;
794 0 : rXclLength2 = 0x0004;
795 : }
796 : else
797 : {
798 0 : rpData->nType = EXC_CHTR_TYPE_DOUBLE;
799 0 : rpData->nSize = 8;
800 0 : rXclLength1 = 0x00000042;
801 0 : rXclLength2 = 0x0008;
802 : }
803 : }
804 0 : break;
805 : case CELLTYPE_STRING:
806 : case CELLTYPE_EDIT:
807 : {
808 0 : OUString sCellStr;
809 0 : if (rScCell.meType == CELLTYPE_STRING)
810 : {
811 0 : sCellStr = rScCell.mpString->getString();
812 0 : rpData->mpFormattedString = XclExpStringHelper::CreateCellString(
813 0 : rRoot, sCellStr, NULL);
814 : }
815 : else
816 : {
817 0 : XclExpHyperlinkHelper aLinkHelper( rRoot, aPosition );
818 0 : if (rScCell.mpEditText)
819 : {
820 0 : sCellStr = ScEditUtil::GetString(*rScCell.mpEditText, &GetDoc());
821 0 : rpData->mpFormattedString = XclExpStringHelper::CreateCellString(
822 0 : rRoot, *rScCell.mpEditText, NULL, aLinkHelper);
823 : }
824 : else
825 : {
826 0 : rpData->mpFormattedString = XclExpStringHelper::CreateCellString(
827 0 : rRoot, EMPTY_OUSTRING, NULL);
828 0 : }
829 : }
830 0 : rpData->pString = new XclExpString( sCellStr, EXC_STR_DEFAULT, 32766 );
831 0 : rpData->nType = EXC_CHTR_TYPE_STRING;
832 0 : rpData->nSize = 3 + rpData->pString->GetSize();
833 0 : rXclLength1 = 64 + (sCellStr.getLength() << 1);
834 0 : rXclLength2 = 6 + (sal_uInt16)(sCellStr.getLength() << 1);
835 : }
836 0 : break;
837 : case CELLTYPE_FORMULA:
838 : {
839 0 : const ScFormulaCell* pFmlCell = rScCell.mpFormula;
840 0 : rpData->mpFormulaCell = pFmlCell;
841 :
842 0 : const ScTokenArray* pTokenArray = pFmlCell->GetCode();
843 0 : if( pTokenArray )
844 : {
845 0 : XclExpRefLog& rRefLog = rpData->maRefLog;
846 0 : rpData->mxTokArr = GetFormulaCompiler().CreateFormula(
847 0 : EXC_FMLATYPE_CELL, *pTokenArray, &pFmlCell->aPos, &rRefLog );
848 0 : rpData->nType = EXC_CHTR_TYPE_FORMULA;
849 0 : sal_Size nSize = rpData->mxTokArr->GetSize() + 3;
850 :
851 0 : for( XclExpRefLog::const_iterator aIt = rRefLog.begin(), aEnd = rRefLog.end(); aIt != aEnd; ++aIt )
852 : {
853 0 : if( aIt->mpUrl && aIt->mpFirstTab )
854 0 : nSize += aIt->mpUrl->GetSize() + aIt->mpFirstTab->GetSize() + 2;
855 : else
856 0 : nSize += (aIt->mnFirstXclTab == aIt->mnLastXclTab) ? 6 : 8;
857 : }
858 0 : rpData->nSize = ::std::min< sal_Size >( nSize, 0xFFFF );
859 0 : rXclLength1 = 0x00000052;
860 0 : rXclLength2 = 0x0018;
861 : }
862 : }
863 0 : break;
864 : default:;
865 : }
866 : }
867 :
868 0 : void XclExpChTrCellContent::SaveActionData( XclExpStream& rStrm ) const
869 : {
870 0 : WriteTabId( rStrm, aPosition.Tab() );
871 0 : rStrm << (sal_uInt16)((pOldData ? (pOldData->nType << 3) : 0x0000) | (pNewData ? pNewData->nType : 0x0000))
872 0 : << (sal_uInt16) 0x0000;
873 0 : Write2DAddress( rStrm, aPosition );
874 0 : rStrm << nOldLength
875 0 : << (sal_uInt32) 0x00000000;
876 0 : if( pOldData )
877 0 : pOldData->Write( rStrm, rIdBuffer );
878 0 : if( pNewData )
879 0 : pNewData->Write( rStrm, rIdBuffer );
880 0 : }
881 :
882 0 : sal_uInt16 XclExpChTrCellContent::GetNum() const
883 : {
884 0 : return 0x013B;
885 : }
886 :
887 0 : sal_Size XclExpChTrCellContent::GetActionByteCount() const
888 : {
889 0 : sal_Size nLen = 16;
890 0 : if( pOldData )
891 0 : nLen += pOldData->nSize;
892 0 : if( pNewData )
893 0 : nLen += pNewData->nSize;
894 0 : return nLen;
895 : }
896 :
897 0 : static const char* lcl_GetType( XclExpChTrData* pData )
898 : {
899 0 : switch( pData->nType )
900 : {
901 : case EXC_CHTR_TYPE_RK:
902 : case EXC_CHTR_TYPE_DOUBLE:
903 0 : return "n";
904 : break;
905 : case EXC_CHTR_TYPE_FORMULA:
906 : {
907 0 : ScFormulaCell* pFormulaCell = const_cast< ScFormulaCell* >( pData->mpFormulaCell );
908 : const char* sType;
909 0 : OUString sValue;
910 0 : XclXmlUtils::GetFormulaTypeAndValue( *pFormulaCell, sType, sValue );
911 0 : return sType;
912 : }
913 : break;
914 : case EXC_CHTR_TYPE_STRING:
915 0 : return "inlineStr";
916 : break;
917 : default:
918 0 : break;
919 : }
920 0 : return "*unknown*";
921 : }
922 :
923 0 : static void lcl_WriteCell( XclExpXmlStream& rStrm, sal_Int32 nElement, const ScAddress& rPosition, XclExpChTrData* pData )
924 : {
925 0 : sax_fastparser::FSHelperPtr pStream = rStrm.GetCurrentStream();
926 :
927 : pStream->startElement( nElement,
928 : XML_r, XclXmlUtils::ToOString( rPosition ).getStr(),
929 : XML_s, NULL, // OOXTODO: not supported
930 : XML_t, lcl_GetType( pData ),
931 : XML_cm, NULL, // OOXTODO: not supported
932 : XML_vm, NULL, // OOXTODO: not supported
933 : XML_ph, NULL, // OOXTODO: not supported
934 0 : FSEND );
935 0 : switch( pData->nType )
936 : {
937 : case EXC_CHTR_TYPE_RK:
938 : case EXC_CHTR_TYPE_DOUBLE:
939 0 : pStream->startElement( XML_v, FSEND );
940 0 : pStream->write( pData->fValue );
941 0 : pStream->endElement( XML_v );
942 0 : break;
943 : case EXC_CHTR_TYPE_FORMULA:
944 : pStream->startElement( XML_f,
945 : // OOXTODO: other attributes? see XclExpFormulaCell::SaveXml()
946 0 : FSEND );
947 : pStream->writeEscaped( XclXmlUtils::ToOUString(
948 0 : *pData->mpFormulaCell->GetDocument(),
949 0 : pData->mpFormulaCell->aPos, pData->mpFormulaCell->GetCode()));
950 0 : pStream->endElement( XML_f );
951 0 : break;
952 : case EXC_CHTR_TYPE_STRING:
953 0 : pStream->startElement( XML_is, FSEND );
954 0 : if( pData->mpFormattedString )
955 0 : pData->mpFormattedString->WriteXml( rStrm );
956 : else
957 0 : pData->pString->WriteXml( rStrm );
958 0 : pStream->endElement( XML_is );
959 0 : break;
960 : default:
961 : // ignore
962 0 : break;
963 : }
964 0 : pStream->endElement( nElement );
965 0 : }
966 :
967 0 : void XclExpChTrCellContent::SaveXml( XclExpXmlStream& rRevisionLogStrm )
968 : {
969 0 : sax_fastparser::FSHelperPtr pStream = rRevisionLogStrm.GetCurrentStream();
970 : pStream->startElement( XML_rcc,
971 : XML_rId, OString::number( GetActionNumber() ).getStr(),
972 0 : XML_ua, XclXmlUtils::ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
973 : XML_ra, NULL, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
974 0 : XML_sId, OString::number( GetTabId( aPosition.Tab() ) ).getStr(),
975 : XML_odxf, NULL, // OOXTODO: not supported
976 : XML_xfDxf, NULL, // OOXTODO: not supported
977 : XML_s, NULL, // OOXTODO: not supported
978 : XML_dxf, NULL, // OOXTODO: not supported
979 : XML_numFmtId, NULL, // OOXTODO: not supported
980 : XML_quotePrefix, NULL, // OOXTODO: not supported
981 : XML_oldQuotePrefix, NULL, // OOXTODO: not supported
982 : XML_ph, NULL, // OOXTODO: not supported
983 : XML_oldPh, NULL, // OOXTODO: not supported
984 : XML_endOfListFormulaUpdate, NULL, // OOXTODO: not supported
985 0 : FSEND );
986 0 : if( pOldData )
987 : {
988 0 : lcl_WriteCell( rRevisionLogStrm, XML_oc, aPosition, pOldData );
989 : }
990 0 : if( pNewData )
991 : {
992 0 : lcl_WriteCell( rRevisionLogStrm, XML_nc, aPosition, pNewData );
993 : }
994 : // OOXTODO: XML_odxf, XML_ndxf, XML_extLst elements
995 0 : pStream->endElement( XML_rcc );
996 0 : }
997 :
998 0 : XclExpChTrInsert::XclExpChTrInsert(
999 : const ScChangeAction& rAction,
1000 : const XclExpRoot& rRoot,
1001 : const XclExpChTrTabIdBuffer& rTabIdBuffer,
1002 : ScChangeTrack& rChangeTrack ) :
1003 : XclExpChTrAction( rAction, rRoot, rTabIdBuffer ),
1004 0 : aRange( rAction.GetBigRange().MakeRange() )
1005 : {
1006 0 : nLength = 0x00000030;
1007 0 : switch( rAction.GetType() )
1008 : {
1009 0 : case SC_CAT_INSERT_COLS: nOpCode = EXC_CHTR_OP_INSCOL; break;
1010 0 : case SC_CAT_INSERT_ROWS: nOpCode = EXC_CHTR_OP_INSROW; break;
1011 0 : case SC_CAT_DELETE_COLS: nOpCode = EXC_CHTR_OP_DELCOL; break;
1012 0 : case SC_CAT_DELETE_ROWS: nOpCode = EXC_CHTR_OP_DELROW; break;
1013 : default:
1014 : OSL_FAIL( "XclExpChTrInsert::XclExpChTrInsert - unknown action" );
1015 : }
1016 :
1017 0 : if( nOpCode & EXC_CHTR_OP_COLFLAG )
1018 : {
1019 0 : aRange.aStart.SetRow( 0 );
1020 0 : aRange.aEnd.SetRow( rRoot.GetXclMaxPos().Row() );
1021 : }
1022 : else
1023 : {
1024 0 : aRange.aStart.SetCol( 0 );
1025 0 : aRange.aEnd.SetCol( rRoot.GetXclMaxPos().Col() );
1026 : }
1027 :
1028 0 : if( nOpCode & EXC_CHTR_OP_DELFLAG )
1029 : {
1030 0 : SetAddAction( new XclExpChTr0x014A( *this ) );
1031 0 : AddDependentContents( rAction, rRoot, rChangeTrack );
1032 : }
1033 0 : }
1034 :
1035 0 : XclExpChTrInsert::~XclExpChTrInsert()
1036 : {
1037 0 : }
1038 :
1039 0 : void XclExpChTrInsert::SaveActionData( XclExpStream& rStrm ) const
1040 : {
1041 0 : WriteTabId( rStrm, aRange.aStart.Tab() );
1042 0 : rStrm << (sal_uInt16) 0x0000;
1043 0 : Write2DRange( rStrm, aRange );
1044 0 : rStrm << (sal_uInt32) 0x00000000;
1045 0 : }
1046 :
1047 0 : void XclExpChTrInsert::PrepareSaveAction( XclExpStream& rStrm ) const
1048 : {
1049 0 : if( (nOpCode == EXC_CHTR_OP_DELROW) || (nOpCode == EXC_CHTR_OP_DELCOL) )
1050 0 : XclExpChTrEmpty( 0x0150 ).Save( rStrm );
1051 0 : }
1052 :
1053 0 : void XclExpChTrInsert::CompleteSaveAction( XclExpStream& rStrm ) const
1054 : {
1055 0 : if( (nOpCode == EXC_CHTR_OP_DELROW) || (nOpCode == EXC_CHTR_OP_DELCOL) )
1056 0 : XclExpChTrEmpty( 0x0151 ).Save( rStrm );
1057 0 : }
1058 :
1059 0 : sal_uInt16 XclExpChTrInsert::GetNum() const
1060 : {
1061 0 : return 0x0137;
1062 : }
1063 :
1064 0 : sal_Size XclExpChTrInsert::GetActionByteCount() const
1065 : {
1066 0 : return 16;
1067 : }
1068 :
1069 0 : static const char* lcl_GetAction( sal_uInt16 nOpCode )
1070 : {
1071 0 : switch( nOpCode )
1072 : {
1073 0 : case EXC_CHTR_OP_INSCOL: return "insertCol";
1074 0 : case EXC_CHTR_OP_INSROW: return "insertRow";
1075 0 : case EXC_CHTR_OP_DELCOL: return "deleteCol";
1076 0 : case EXC_CHTR_OP_DELROW: return "deleteRow";
1077 0 : default: return "*unknown*";
1078 : }
1079 : }
1080 :
1081 0 : void XclExpChTrInsert::SaveXml( XclExpXmlStream& rRevisionLogStrm )
1082 : {
1083 0 : sax_fastparser::FSHelperPtr pStream = rRevisionLogStrm.GetCurrentStream();
1084 : pStream->startElement( XML_rrc,
1085 : XML_rId, OString::number( GetActionNumber() ).getStr(),
1086 0 : XML_ua, XclXmlUtils::ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1087 : XML_ra, NULL, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1088 0 : XML_sId, OString::number( GetTabId( aRange.aStart.Tab() ) ).getStr(),
1089 : XML_eol, NULL, // OOXTODO: not supported?
1090 : XML_ref, XclXmlUtils::ToOString( aRange ).getStr(),
1091 : XML_action, lcl_GetAction( nOpCode ),
1092 : XML_edge, NULL, // OOXTODO: ???
1093 0 : FSEND );
1094 : // OOXTODO: does this handle XML_rfmt, XML_undo?
1095 0 : XclExpChTrAction* pAction = GetAddAction();
1096 0 : while( pAction != NULL )
1097 : {
1098 0 : pAction->SaveXml( rRevisionLogStrm );
1099 0 : pAction = pAction->GetAddAction();
1100 : }
1101 0 : pStream->endElement( XML_rrc );
1102 0 : }
1103 :
1104 0 : XclExpChTrInsertTab::XclExpChTrInsertTab(
1105 : const ScChangeAction& rAction,
1106 : const XclExpRoot& rRoot,
1107 : const XclExpChTrTabIdBuffer& rTabIdBuffer ) :
1108 : XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_INSTAB ),
1109 : XclExpRoot( rRoot ),
1110 0 : nTab( (SCTAB) rAction.GetBigRange().aStart.Tab() )
1111 : {
1112 0 : nLength = 0x0000021C;
1113 0 : bForceInfo = true;
1114 0 : }
1115 :
1116 0 : XclExpChTrInsertTab::~XclExpChTrInsertTab()
1117 : {
1118 0 : }
1119 :
1120 0 : void XclExpChTrInsertTab::SaveActionData( XclExpStream& rStrm ) const
1121 : {
1122 0 : WriteTabId( rStrm, nTab );
1123 0 : rStrm << sal_uInt32( 0 );
1124 0 : lcl_WriteFixedString( rStrm, XclExpString( GetTabInfo().GetScTabName( nTab ) ), 127 );
1125 0 : lcl_WriteDateTime( rStrm, GetDateTime() );
1126 0 : rStrm.WriteZeroBytes( 133 );
1127 0 : }
1128 :
1129 0 : sal_uInt16 XclExpChTrInsertTab::GetNum() const
1130 : {
1131 0 : return 0x014D;
1132 : }
1133 :
1134 0 : sal_Size XclExpChTrInsertTab::GetActionByteCount() const
1135 : {
1136 0 : return 276;
1137 : }
1138 :
1139 0 : void XclExpChTrInsertTab::SaveXml( XclExpXmlStream& rStrm )
1140 : {
1141 0 : sax_fastparser::FSHelperPtr pStream = rStrm.GetCurrentStream();
1142 : pStream->singleElement( XML_ris,
1143 : XML_rId, OString::number( GetActionNumber() ).getStr(),
1144 0 : XML_ua, XclXmlUtils::ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1145 : XML_ra, NULL, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1146 0 : XML_sheetId, OString::number( GetTabId( nTab ) ).getStr(),
1147 0 : XML_name, XclXmlUtils::ToOString( GetTabInfo().GetScTabName( nTab ) ).getStr(),
1148 : XML_sheetPosition, OString::number( nTab ).getStr(),
1149 0 : FSEND );
1150 0 : }
1151 :
1152 0 : XclExpChTrMoveRange::XclExpChTrMoveRange(
1153 : const ScChangeActionMove& rAction,
1154 : const XclExpRoot& rRoot,
1155 : const XclExpChTrTabIdBuffer& rTabIdBuffer,
1156 : ScChangeTrack& rChangeTrack ) :
1157 : XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_MOVE ),
1158 0 : aDestRange( rAction.GetBigRange().MakeRange() )
1159 : {
1160 0 : nLength = 0x00000042;
1161 0 : aSourceRange = aDestRange;
1162 : sal_Int32 nDCols, nDRows, nDTabs;
1163 0 : rAction.GetDelta( nDCols, nDRows, nDTabs );
1164 0 : aSourceRange.aStart.IncRow( (SCROW) -nDRows );
1165 0 : aSourceRange.aStart.IncCol( (SCCOL) -nDCols );
1166 0 : aSourceRange.aStart.IncTab( (SCTAB) -nDTabs );
1167 0 : aSourceRange.aEnd.IncRow( (SCROW) -nDRows );
1168 0 : aSourceRange.aEnd.IncCol( (SCCOL) -nDCols );
1169 0 : aSourceRange.aEnd.IncTab( (SCTAB) -nDTabs );
1170 0 : AddDependentContents( rAction, rRoot, rChangeTrack );
1171 0 : }
1172 :
1173 0 : XclExpChTrMoveRange::~XclExpChTrMoveRange()
1174 : {
1175 0 : }
1176 :
1177 0 : void XclExpChTrMoveRange::SaveActionData( XclExpStream& rStrm ) const
1178 : {
1179 0 : WriteTabId( rStrm, aDestRange.aStart.Tab() );
1180 0 : Write2DRange( rStrm, aSourceRange );
1181 0 : Write2DRange( rStrm, aDestRange );
1182 0 : WriteTabId( rStrm, aSourceRange.aStart.Tab() );
1183 0 : rStrm << (sal_uInt32) 0x00000000;
1184 0 : }
1185 :
1186 0 : void XclExpChTrMoveRange::PrepareSaveAction( XclExpStream& rStrm ) const
1187 : {
1188 0 : XclExpChTrEmpty( 0x014E ).Save( rStrm );
1189 0 : }
1190 :
1191 0 : void XclExpChTrMoveRange::CompleteSaveAction( XclExpStream& rStrm ) const
1192 : {
1193 0 : XclExpChTrEmpty( 0x014F ).Save( rStrm );
1194 0 : }
1195 :
1196 0 : sal_uInt16 XclExpChTrMoveRange::GetNum() const
1197 : {
1198 0 : return 0x0140;
1199 : }
1200 :
1201 0 : sal_Size XclExpChTrMoveRange::GetActionByteCount() const
1202 : {
1203 0 : return 24;
1204 : }
1205 :
1206 0 : void XclExpChTrMoveRange::SaveXml( XclExpXmlStream& rRevisionLogStrm )
1207 : {
1208 0 : sax_fastparser::FSHelperPtr pStream = rRevisionLogStrm.GetCurrentStream();
1209 :
1210 : pStream->startElement( XML_rm,
1211 : XML_rId, OString::number( GetActionNumber() ).getStr(),
1212 0 : XML_ua, XclXmlUtils::ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1213 : XML_ra, NULL, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1214 0 : XML_sheetId, OString::number( GetTabId( aDestRange.aStart.Tab() ) ).getStr(),
1215 : XML_source, XclXmlUtils::ToOString( aSourceRange ).getStr(),
1216 : XML_destination, XclXmlUtils::ToOString( aDestRange ).getStr(),
1217 0 : XML_sourceSheetId, OString::number( GetTabId( aSourceRange.aStart.Tab() ) ).getStr(),
1218 0 : FSEND );
1219 : // OOXTODO: does this handle XML_rfmt, XML_undo?
1220 0 : XclExpChTrAction* pAction = GetAddAction();
1221 0 : while( pAction != NULL )
1222 : {
1223 0 : pAction->SaveXml( rRevisionLogStrm );
1224 0 : pAction = pAction->GetAddAction();
1225 : }
1226 0 : pStream->endElement( XML_rm );
1227 0 : }
1228 :
1229 0 : XclExpChTr0x014A::XclExpChTr0x014A( const XclExpChTrInsert& rAction ) :
1230 0 : XclExpChTrInsert( rAction )
1231 : {
1232 0 : nLength = 0x00000026;
1233 0 : nOpCode = EXC_CHTR_OP_FORMAT;
1234 0 : }
1235 :
1236 0 : XclExpChTr0x014A::~XclExpChTr0x014A()
1237 : {
1238 0 : }
1239 :
1240 0 : void XclExpChTr0x014A::SaveActionData( XclExpStream& rStrm ) const
1241 : {
1242 0 : WriteTabId( rStrm, aRange.aStart.Tab() );
1243 0 : rStrm << (sal_uInt16) 0x0003
1244 0 : << (sal_uInt16) 0x0001;
1245 0 : Write2DRange( rStrm, aRange );
1246 0 : }
1247 :
1248 0 : sal_uInt16 XclExpChTr0x014A::GetNum() const
1249 : {
1250 0 : return 0x014A;
1251 : }
1252 :
1253 0 : sal_Size XclExpChTr0x014A::GetActionByteCount() const
1254 : {
1255 0 : return 14;
1256 : }
1257 :
1258 0 : void XclExpChTr0x014A::SaveXml( XclExpXmlStream& rStrm )
1259 : {
1260 0 : sax_fastparser::FSHelperPtr pStream = rStrm.GetCurrentStream();
1261 :
1262 : pStream->startElement( XML_rfmt,
1263 0 : XML_sheetId, OString::number( GetTabId( aRange.aStart.Tab() ) ).getStr(),
1264 : XML_xfDxf, NULL, // OOXTODO: not supported
1265 : XML_s, NULL, // OOXTODO: style
1266 : XML_sqref, XclXmlUtils::ToOString( aRange ).getStr(),
1267 : XML_start, NULL, // OOXTODO: for string changes
1268 : XML_length, NULL, // OOXTODO: for string changes
1269 0 : FSEND );
1270 : // OOXTODO: XML_dxf, XML_extLst
1271 :
1272 0 : pStream->endElement( XML_rfmt );
1273 0 : }
1274 :
1275 0 : class ExcXmlRecord : public ExcRecord
1276 : {
1277 : public:
1278 : virtual sal_Size GetLen() const SAL_OVERRIDE;
1279 : virtual sal_uInt16 GetNum() const SAL_OVERRIDE;
1280 : virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
1281 : };
1282 :
1283 0 : sal_Size ExcXmlRecord::GetLen() const
1284 : {
1285 0 : return 0;
1286 : }
1287 :
1288 0 : sal_uInt16 ExcXmlRecord::GetNum() const
1289 : {
1290 0 : return 0;
1291 : }
1292 :
1293 0 : void ExcXmlRecord::Save( XclExpStream& )
1294 : {
1295 : // Do nothing; ignored for BIFF output.
1296 0 : }
1297 :
1298 0 : class StartXmlElement : public ExcXmlRecord
1299 : {
1300 : public:
1301 : enum Behavior {
1302 : CLOSE_ELEMENT = 0x1,
1303 : WRITE_NAMESPACES = 0x2,
1304 : };
1305 0 : StartXmlElement( sal_Int32 nElement, sal_Int32 eBehavior )
1306 0 : : mnElement( nElement ), meBehavior( (Behavior) eBehavior ) {}
1307 : virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
1308 : private:
1309 : sal_Int32 mnElement;
1310 : Behavior meBehavior;
1311 : };
1312 :
1313 0 : void StartXmlElement::SaveXml( XclExpXmlStream& rStrm )
1314 : {
1315 0 : sax_fastparser::FSHelperPtr pStream = rStrm.GetCurrentStream();
1316 : pStream->write( "<" )
1317 0 : ->writeId( mnElement );
1318 0 : if( meBehavior & WRITE_NAMESPACES )
1319 : {
1320 : rStrm.WriteAttributes(
1321 : XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
1322 : FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
1323 0 : FSEND );
1324 : }
1325 0 : if( meBehavior & CLOSE_ELEMENT )
1326 : {
1327 0 : pStream->write( ">" );
1328 0 : }
1329 0 : }
1330 :
1331 0 : class EndXmlElement : public ExcXmlRecord
1332 : {
1333 : sal_Int32 mnElement;
1334 : public:
1335 0 : EndXmlElement( sal_Int32 nElement ) : mnElement( nElement) {}
1336 : virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
1337 : };
1338 :
1339 0 : void EndXmlElement::SaveXml( XclExpXmlStream& rStrm )
1340 : {
1341 0 : rStrm.GetCurrentStream()->endElement( mnElement );
1342 0 : }
1343 :
1344 0 : class EndHeaderElement : public EndXmlElement
1345 : {
1346 : public:
1347 0 : EndHeaderElement() : EndXmlElement( XML_header ) {}
1348 : virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
1349 : };
1350 :
1351 0 : void EndHeaderElement::SaveXml( XclExpXmlStream& rStrm )
1352 : {
1353 : // Remove the `xl/revisions/revisionLogX.xml' file from the stack
1354 0 : rStrm.PopStream();
1355 :
1356 0 : EndXmlElement::SaveXml( rStrm );
1357 0 : }
1358 :
1359 0 : XclExpChangeTrack::XclExpChangeTrack( const XclExpRoot& rRoot ) :
1360 : XclExpRoot( rRoot ),
1361 : aActionStack(),
1362 : pTabIdBuffer( NULL ),
1363 : pTempDoc( NULL ),
1364 : pHeader( NULL ),
1365 0 : bValidGUID( false )
1366 : {
1367 : OSL_ENSURE( GetOldRoot().pTabId, "XclExpChangeTrack::XclExpChangeTrack - root data incomplete" );
1368 0 : if( !GetOldRoot().pTabId )
1369 0 : return;
1370 :
1371 0 : ScChangeTrack* pTempChangeTrack = CreateTempChangeTrack();
1372 0 : if (!pTempChangeTrack)
1373 0 : return;
1374 :
1375 0 : pTabIdBuffer = new XclExpChTrTabIdBuffer( GetTabInfo().GetXclTabCount() );
1376 0 : maBuffers.push_back( pTabIdBuffer );
1377 :
1378 : // calculate final table order (tab id list)
1379 : const ScChangeAction* pScAction;
1380 0 : for( pScAction = pTempChangeTrack->GetLast(); pScAction; pScAction = pScAction->GetPrev() )
1381 : {
1382 0 : if( pScAction->GetType() == SC_CAT_INSERT_TABS )
1383 : {
1384 0 : SCTAB nScTab = static_cast< SCTAB >( pScAction->GetBigRange().aStart.Tab() );
1385 0 : pTabIdBuffer->InitFill( GetTabInfo().GetXclTab( nScTab ) );
1386 : }
1387 : }
1388 0 : pTabIdBuffer->InitFillup();
1389 0 : GetOldRoot().pTabId->Copy( *pTabIdBuffer );
1390 :
1391 : // get actions in reverse order
1392 0 : pScAction = pTempChangeTrack->GetLast();
1393 0 : while( pScAction )
1394 : {
1395 0 : PushActionRecord( *pScAction );
1396 0 : const ScChangeAction* pPrevAction = pScAction->GetPrev();
1397 0 : pTempChangeTrack->Undo( pScAction->GetActionNumber(), pScAction->GetActionNumber() );
1398 0 : pScAction = pPrevAction;
1399 : }
1400 :
1401 : // build record list
1402 0 : pHeader = new XclExpChTrHeader;
1403 0 : aRecList.push_back( new StartXmlElement( XML_headers, StartXmlElement::WRITE_NAMESPACES ) );
1404 0 : aRecList.push_back( pHeader );
1405 0 : aRecList.push_back( new XclExpChTr0x0195 );
1406 0 : aRecList.push_back( new XclExpChTr0x0194( *pTempChangeTrack ) );
1407 :
1408 0 : OUString sLastUsername;
1409 0 : DateTime aLastDateTime( DateTime::EMPTY );
1410 0 : sal_uInt32 nIndex = 1;
1411 0 : sal_Int32 nLogNumber = 1;
1412 0 : while( !aActionStack.empty() )
1413 : {
1414 0 : XclExpChTrAction* pAction = aActionStack.top();
1415 0 : aActionStack.pop();
1416 :
1417 0 : if( (nIndex == 1) || pAction->ForceInfoRecord() ||
1418 0 : (pAction->GetUsername() != sLastUsername) ||
1419 0 : (pAction->GetDateTime() != aLastDateTime) )
1420 : {
1421 0 : if( nIndex != 1 )
1422 : {
1423 0 : aRecList.push_back( new EndXmlElement( XML_revisions ) );
1424 0 : aRecList.push_back( new EndHeaderElement() );
1425 : }
1426 :
1427 0 : lcl_GenerateGUID( aGUID, bValidGUID );
1428 0 : sLastUsername = pAction->GetUsername();
1429 0 : aLastDateTime = pAction->GetDateTime();
1430 :
1431 0 : aRecList.push_back( new StartXmlElement( XML_header, 0 ) );
1432 0 : aRecList.push_back( new XclExpChTrInfo( sLastUsername, aLastDateTime, aGUID, nLogNumber++ ) );
1433 0 : aRecList.push_back( new XclExpChTrTabId( pAction->GetTabIdBuffer(), true ) );
1434 0 : aRecList.push_back( new StartXmlElement( XML_revisions, StartXmlElement::WRITE_NAMESPACES | StartXmlElement::CLOSE_ELEMENT ) );
1435 0 : pHeader->SetGUID( aGUID );
1436 : }
1437 0 : pAction->SetIndex( nIndex );
1438 0 : aRecList.push_back( pAction );
1439 : }
1440 :
1441 0 : pHeader->SetGUID( aGUID );
1442 0 : pHeader->SetCount( nIndex - 1 );
1443 0 : if( nLogNumber > 1 )
1444 : {
1445 0 : aRecList.push_back( new EndXmlElement( XML_revisions ) );
1446 0 : aRecList.push_back( new EndHeaderElement() );
1447 : }
1448 0 : aRecList.push_back( new EndXmlElement( XML_headers ) );
1449 0 : aRecList.push_back( new ExcEof );
1450 : }
1451 :
1452 0 : XclExpChangeTrack::~XclExpChangeTrack()
1453 : {
1454 0 : std::vector<ExcRecord*>::iterator prIter;
1455 0 : for ( prIter = aRecList.begin(); prIter != aRecList.end(); ++prIter )
1456 0 : delete *prIter;
1457 :
1458 0 : std::vector<XclExpChTrTabIdBuffer*>::iterator pIter;
1459 0 : for ( pIter = maBuffers.begin(); pIter != maBuffers.end(); ++pIter )
1460 0 : delete *pIter;
1461 :
1462 0 : while( !aActionStack.empty() )
1463 : {
1464 0 : delete aActionStack.top();
1465 0 : aActionStack.pop();
1466 : }
1467 :
1468 0 : if( pTempDoc )
1469 0 : delete pTempDoc;
1470 0 : }
1471 :
1472 0 : ScChangeTrack* XclExpChangeTrack::CreateTempChangeTrack()
1473 : {
1474 : // get original change track
1475 0 : ScChangeTrack* pOrigChangeTrack = GetDoc().GetChangeTrack();
1476 : OSL_ENSURE( pOrigChangeTrack, "XclExpChangeTrack::CreateTempChangeTrack - no change track data" );
1477 0 : if( !pOrigChangeTrack )
1478 0 : return NULL;
1479 :
1480 : // create empty document
1481 0 : pTempDoc = new ScDocument;
1482 : OSL_ENSURE( pTempDoc, "XclExpChangeTrack::CreateTempChangeTrack - no temp document" );
1483 0 : if( !pTempDoc )
1484 0 : return NULL;
1485 :
1486 : // adjust table count
1487 0 : SCTAB nOrigCount = GetDoc().GetTableCount();
1488 0 : OUString sTabName;
1489 0 : for( sal_Int32 nIndex = 0; nIndex < nOrigCount; nIndex++ )
1490 : {
1491 0 : pTempDoc->CreateValidTabName( sTabName );
1492 0 : pTempDoc->InsertTab( SC_TAB_APPEND, sTabName );
1493 : }
1494 : OSL_ENSURE( nOrigCount == pTempDoc->GetTableCount(),
1495 : "XclExpChangeTrack::CreateTempChangeTrack - table count mismatch" );
1496 0 : if( nOrigCount != pTempDoc->GetTableCount() )
1497 0 : return NULL;
1498 :
1499 0 : return pOrigChangeTrack->Clone(pTempDoc);
1500 : }
1501 :
1502 0 : void XclExpChangeTrack::PushActionRecord( const ScChangeAction& rAction )
1503 : {
1504 0 : XclExpChTrAction* pXclAction = NULL;
1505 0 : ScChangeTrack* pTempChangeTrack = pTempDoc->GetChangeTrack();
1506 0 : switch( rAction.GetType() )
1507 : {
1508 : case SC_CAT_CONTENT:
1509 0 : pXclAction = new XclExpChTrCellContent( (const ScChangeActionContent&) rAction, GetRoot(), *pTabIdBuffer );
1510 0 : break;
1511 : case SC_CAT_INSERT_ROWS:
1512 : case SC_CAT_INSERT_COLS:
1513 : case SC_CAT_DELETE_ROWS:
1514 : case SC_CAT_DELETE_COLS:
1515 0 : if (pTempChangeTrack)
1516 0 : pXclAction = new XclExpChTrInsert( rAction, GetRoot(), *pTabIdBuffer, *pTempChangeTrack );
1517 0 : break;
1518 : case SC_CAT_INSERT_TABS:
1519 : {
1520 0 : pXclAction = new XclExpChTrInsertTab( rAction, GetRoot(), *pTabIdBuffer );
1521 0 : XclExpChTrTabIdBuffer* pNewBuffer = new XclExpChTrTabIdBuffer( *pTabIdBuffer );
1522 0 : pNewBuffer->Remove();
1523 0 : maBuffers.push_back( pNewBuffer );
1524 0 : pTabIdBuffer = pNewBuffer;
1525 : }
1526 0 : break;
1527 : case SC_CAT_MOVE:
1528 0 : if (pTempChangeTrack)
1529 0 : pXclAction = new XclExpChTrMoveRange( (const ScChangeActionMove&) rAction, GetRoot(), *pTabIdBuffer, *pTempChangeTrack );
1530 0 : break;
1531 : default:;
1532 : }
1533 0 : if( pXclAction )
1534 0 : aActionStack.push( pXclAction );
1535 0 : }
1536 :
1537 0 : bool XclExpChangeTrack::WriteUserNamesStream()
1538 : {
1539 0 : bool bRet = false;
1540 0 : SotStorageStreamRef xSvStrm = OpenStream( EXC_STREAM_USERNAMES );
1541 : OSL_ENSURE( xSvStrm.Is(), "XclExpChangeTrack::WriteUserNamesStream - no stream" );
1542 0 : if( xSvStrm.Is() )
1543 : {
1544 0 : XclExpStream aXclStrm( *xSvStrm, GetRoot() );
1545 0 : XclExpChTr0x0191().Save( aXclStrm );
1546 0 : XclExpChTr0x0198().Save( aXclStrm );
1547 0 : XclExpChTr0x0192().Save( aXclStrm );
1548 0 : XclExpChTr0x0197().Save( aXclStrm );
1549 0 : xSvStrm->Commit();
1550 0 : bRet = true;
1551 : }
1552 0 : return bRet;
1553 : }
1554 :
1555 0 : void XclExpChangeTrack::Write()
1556 : {
1557 0 : if( aRecList.empty() )
1558 0 : return;
1559 :
1560 0 : if( WriteUserNamesStream() )
1561 : {
1562 0 : SotStorageStreamRef xSvStrm = OpenStream( EXC_STREAM_REVLOG );
1563 : OSL_ENSURE( xSvStrm.Is(), "XclExpChangeTrack::Write - no stream" );
1564 0 : if( xSvStrm.Is() )
1565 : {
1566 0 : XclExpStream aXclStrm( *xSvStrm, GetRoot(), EXC_MAXRECSIZE_BIFF8 + 8 );
1567 :
1568 0 : std::vector<ExcRecord*>::iterator pIter;
1569 0 : for ( pIter = aRecList.begin(); pIter != aRecList.end(); ++pIter )
1570 0 : (*pIter)->Save(aXclStrm);
1571 :
1572 0 : xSvStrm->Commit();
1573 0 : }
1574 : }
1575 : }
1576 :
1577 0 : static void lcl_WriteUserNamesXml( XclExpXmlStream& rWorkbookStrm )
1578 : {
1579 : sax_fastparser::FSHelperPtr pUserNames = rWorkbookStrm.CreateOutputStream(
1580 : OUString( "xl/revisions/userNames.xml" ),
1581 : OUString( "revisions/userNames.xml" ),
1582 0 : rWorkbookStrm.GetCurrentStream()->getOutputStream(),
1583 : "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml",
1584 0 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/usernames" );
1585 : pUserNames->startElement( XML_users,
1586 : XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
1587 : FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
1588 : XML_count, "0",
1589 0 : FSEND );
1590 : // OOXTODO: XML_userinfo elements for each user editing the file
1591 : // Doesn't seem to be supported by .xls output either (based on
1592 : // contents of XclExpChangeTrack::WriteUserNamesStream()).
1593 0 : pUserNames->endElement( XML_users );
1594 0 : }
1595 :
1596 0 : void XclExpChangeTrack::WriteXml( XclExpXmlStream& rWorkbookStrm )
1597 : {
1598 0 : if( aRecList.empty() )
1599 0 : return;
1600 :
1601 0 : lcl_WriteUserNamesXml( rWorkbookStrm );
1602 :
1603 : sax_fastparser::FSHelperPtr pRevisionHeaders = rWorkbookStrm.CreateOutputStream(
1604 : OUString( "xl/revisions/revisionHeaders.xml" ),
1605 : OUString( "revisions/revisionHeaders.xml" ),
1606 0 : rWorkbookStrm.GetCurrentStream()->getOutputStream(),
1607 : "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml",
1608 0 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionHeaders" );
1609 : // OOXTODO: XML_userinfo elements for each user editing the file
1610 : // Doesn't seem to be supported by .xls output either (based on
1611 : // contents of XclExpChangeTrack::WriteUserNamesStream()).
1612 0 : rWorkbookStrm.PushStream( pRevisionHeaders );
1613 :
1614 0 : std::vector<ExcRecord*>::iterator pIter;
1615 0 : for ( pIter = aRecList.begin(); pIter != aRecList.end(); ++pIter )
1616 0 : (*pIter)->SaveXml(rWorkbookStrm);
1617 :
1618 0 : rWorkbookStrm.PopStream();
1619 0 : }
1620 :
1621 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|