LibreOffice Module sc (master)  1
XclExpChangeTrack.cxx
Go to the documentation of this file.
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 #include <memory>
21 #include <numeric>
22 #include <stdio.h>
23 #include <sot/storage.hxx>
24 #include <XclExpChangeTrack.hxx>
25 #include <xeformula.hxx>
26 #include <xehelper.hxx>
27 #include <xltools.hxx>
28 #include <formulacell.hxx>
29 #include <document.hxx>
30 #include <editutil.hxx>
31 #include <root.hxx>
32 
33 #include <oox/export/utils.hxx>
34 #include <oox/token/namespaces.hxx>
35 #include <oox/token/tokens.hxx>
36 #include <rtl/uuid.h>
37 #include <svl/sharedstring.hxx>
38 
39 using namespace oox;
40 
41 static OString lcl_GuidToOString( sal_uInt8 aGuid[ 16 ] )
42 {
43  char sBuf[ 40 ];
44  snprintf( sBuf, sizeof( sBuf ),
45  "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
46  aGuid[ 0 ], aGuid[ 1 ], aGuid[ 2 ], aGuid[ 3 ], aGuid[ 4 ], aGuid[ 5 ], aGuid[ 6 ], aGuid[ 7 ],
47  aGuid[ 8 ], aGuid[ 9 ], aGuid[ 10 ], aGuid[ 11 ], aGuid[ 12 ], aGuid[ 13 ], aGuid[ 14 ], aGuid[ 15 ] );
48  return sBuf;
49 }
50 
51 static OString lcl_DateTimeToOString( const DateTime& rDateTime )
52 {
53  char sBuf[ 200 ];
54  snprintf( sBuf, sizeof( sBuf ),
55  "%d-%02d-%02dT%02d:%02d:%02d.%09" SAL_PRIuUINT32 "Z",
56  rDateTime.GetYear(), rDateTime.GetMonth(), rDateTime.GetDay(),
57  rDateTime.GetHour(), rDateTime.GetMin(), rDateTime.GetSec(),
58  rDateTime.GetNanoSec() );
59  return sBuf;
60 }
61 
62 // local functions
63 
64 static void lcl_WriteDateTime( XclExpStream& rStrm, const DateTime& rDateTime )
65 {
66  rStrm.SetSliceSize( 7 );
67  rStrm << static_cast<sal_uInt16>(rDateTime.GetYear())
68  << static_cast<sal_uInt8>(rDateTime.GetMonth())
69  << static_cast<sal_uInt8>(rDateTime.GetDay())
70  << static_cast<sal_uInt8>(rDateTime.GetHour())
71  << static_cast<sal_uInt8>(rDateTime.GetMin())
72  << static_cast<sal_uInt8>(rDateTime.GetSec());
73  rStrm.SetSliceSize( 0 );
74 }
75 
76 // write string and fill rest of <nLength> with zero bytes
77 // <nLength> is without string header
78 static void lcl_WriteFixedString( XclExpStream& rStrm, const XclExpString& rString, std::size_t nLength )
79 {
80  std::size_t nStrBytes = rString.GetBufferSize();
81  OSL_ENSURE( nLength >= nStrBytes, "lcl_WriteFixedString - String too long" );
82  if( rString.Len() > 0 )
83  rStrm << rString;
84  if( nLength > nStrBytes )
85  rStrm.WriteZeroBytes( nLength - nStrBytes );
86 }
87 
88 static void lcl_GenerateGUID( sal_uInt8* pGUID, bool& rValidGUID )
89 {
90  rtl_createUuid( pGUID, rValidGUID ? pGUID : nullptr, false );
91  rValidGUID = true;
92 }
93 
94 static void lcl_WriteGUID( XclExpStream& rStrm, const sal_uInt8* pGUID )
95 {
96  rStrm.SetSliceSize( 16 );
97  for( std::size_t nIndex = 0; nIndex < 16; nIndex++ )
98  rStrm << pGUID[ nIndex ];
99  rStrm.SetSliceSize( 0 );
100 }
101 
102 XclExpUserBView::XclExpUserBView( const OUString& rUsername, const sal_uInt8* pGUID ) :
103  sUsername( rUsername )
104 {
105  memcpy( aGUID, pGUID, 16 );
106 }
107 
109 {
110  rStrm << sal_uInt32(0xFF078014)
111  << sal_uInt32(0x00000001);
112  lcl_WriteGUID( rStrm, aGUID );
113  rStrm.WriteZeroBytes( 8 );
114  rStrm << sal_uInt32(1200)
115  << sal_uInt32(1000)
116  << sal_uInt16(1000)
117  << sal_uInt16(0x0CF7)
118  << sal_uInt16(0x0000)
119  << sal_uInt16(0x0001)
120  << sal_uInt16(0x0000);
121  if( sUsername.Len() > 0 )
122  rStrm << sUsername;
123 }
124 
125 sal_uInt16 XclExpUserBView::GetNum() const
126 {
127  return 0x01A9;
128 }
129 
130 std::size_t XclExpUserBView::GetLen() const
131 {
132  return 50 + ((sUsername.Len() > 0) ? sUsername.GetSize() : 0);
133 }
134 
136 {
137  sal_uInt8 aGUID[ 16 ];
138  bool bValidGUID = false;
139  const std::set<OUString>& rStrColl = rChangeTrack.GetUserCollection();
140  aViews.reserve(rStrColl.size());
141  for (const auto& rStr : rStrColl)
142  {
143  lcl_GenerateGUID( aGUID, bValidGUID );
144  aViews.emplace_back( rStr, aGUID );
145  }
146 }
147 
149 {
150 }
151 
153 {
154  for( XclExpUserBView& rView : aViews )
155  rView.Save( rStrm );
156 }
157 
158 XclExpUsersViewBegin::XclExpUsersViewBegin( const sal_uInt8* pGUID, sal_uInt32 nTab ) :
159  nCurrTab( nTab )
160 {
161  memcpy( aGUID, pGUID, 16 );
162 }
163 
165 {
166  lcl_WriteGUID( rStrm, aGUID );
167  rStrm << nCurrTab
168  << sal_uInt32(100)
169  << sal_uInt32(64)
170  << sal_uInt32(3)
171  << sal_uInt32(0x0000003C)
172  << sal_uInt16(0)
173  << sal_uInt16(3)
174  << sal_uInt16(0)
175  << sal_uInt16(3)
176  << double(0)
177  << double(0)
178  << sal_Int16(-1)
179  << sal_Int16(-1);
180 }
181 
183 {
184  return 0x01AA;
185 }
186 
187 std::size_t XclExpUsersViewBegin::GetLen() const
188 {
189  return 64;
190 }
191 
193 {
194  rStrm << sal_uInt16(0x0001);
195 }
196 
197 sal_uInt16 XclExpUsersViewEnd::GetNum() const
198 {
199  return 0x01AB;
200 }
201 
202 std::size_t XclExpUsersViewEnd::GetLen() const
203 {
204  return 2;
205 }
206 
208 {
209  rStrm << sal_uInt16(0x0000);
210 }
211 
212 sal_uInt16 XclExpChTr0x0191::GetNum() const
213 {
214  return 0x0191;
215 }
216 
217 std::size_t XclExpChTr0x0191::GetLen() const
218 {
219  return 2;
220 }
221 
223 {
224  rStrm << sal_uInt16(0x0006)
225  << sal_uInt16(0x0000);
226 }
227 
228 sal_uInt16 XclExpChTr0x0198::GetNum() const
229 {
230  return 0x0198;
231 }
232 
233 std::size_t XclExpChTr0x0198::GetLen() const
234 {
235  return 4;
236 }
237 
239 {
240  rStrm << sal_uInt16( 0x0022 );
241  rStrm.WriteZeroBytes( 510 );
242 }
243 
244 sal_uInt16 XclExpChTr0x0192::GetNum() const
245 {
246  return 0x0192;
247 }
248 
249 std::size_t XclExpChTr0x0192::GetLen() const
250 {
251  return 512;
252 }
253 
255 {
256  rStrm << sal_uInt16(0x0000);
257 }
258 
259 sal_uInt16 XclExpChTr0x0197::GetNum() const
260 {
261  return 0x0197;
262 }
263 
264 std::size_t XclExpChTr0x0197::GetLen() const
265 {
266  return 2;
267 }
268 
270 {
271 }
272 
273 sal_uInt16 XclExpChTrEmpty::GetNum() const
274 {
275  return nRecNum;
276 }
277 
278 std::size_t XclExpChTrEmpty::GetLen() const
279 {
280  return 0;
281 }
282 
284 {
285 }
286 
288 {
289  rStrm.WriteZeroBytes( 162 );
290 }
291 
292 sal_uInt16 XclExpChTr0x0195::GetNum() const
293 {
294  return 0x0195;
295 }
296 
297 std::size_t XclExpChTr0x0195::GetLen() const
298 {
299  return 162;
300 }
301 
303 {
304 }
305 
307 {
308  rStrm << sal_uInt32(0);
309  lcl_WriteDateTime( rStrm, aDateTime );
310  rStrm << sal_uInt8(0);
311  lcl_WriteFixedString( rStrm, sUsername, 147 );
312 }
313 
314 sal_uInt16 XclExpChTr0x0194::GetNum() const
315 {
316  return 0x0194;
317 }
318 
319 std::size_t XclExpChTr0x0194::GetLen() const
320 {
321  return 162;
322 }
323 
325 {
326 }
327 
329 {
330  rStrm << sal_uInt16(0x0006)
331  << sal_uInt16(0x0000)
332  << sal_uInt16(0x000D);
333  lcl_WriteGUID( rStrm, aGUID );
334  lcl_WriteGUID( rStrm, aGUID );
335  rStrm << nCount
336  << sal_uInt16(0x0001)
337  << sal_uInt32(0x00000000)
338  << sal_uInt16(0x001E);
339 }
340 
341 sal_uInt16 XclExpChTrHeader::GetNum() const
342 {
343  return 0x0196;
344 }
345 
346 std::size_t XclExpChTrHeader::GetLen() const
347 {
348  return 50;
349 }
350 
351 void XclExpChTrHeader::SaveXml( XclExpXmlStream& rRevisionHeadersStrm )
352 {
353  sax_fastparser::FSHelperPtr pHeaders = rRevisionHeadersStrm.GetCurrentStream();
354  rRevisionHeadersStrm.WriteAttributes(
355  XML_guid, lcl_GuidToOString(aGUID),
356  XML_lastGuid, nullptr, // OOXTODO
357  XML_shared, nullptr, // OOXTODO
358  XML_diskRevisions, nullptr, // OOXTODO
359  XML_history, nullptr, // OOXTODO
360  XML_trackRevisions, nullptr, // OOXTODO
361  XML_exclusive, nullptr, // OOXTODO
362  XML_revisionId, nullptr, // OOXTODO
363  XML_version, nullptr, // OOXTODO
364  XML_keepChangeHistory, nullptr, // OOXTODO
365  XML_protected, nullptr, // OOXTODO
366  XML_preserveHistory, nullptr); // OOXTODO
367  pHeaders->write( ">" );
368 }
369 
371 {
372  memcpy(maGUID, pGUID, 16);
373 }
374 
376 {
378 
379  pHeaders->write("<")->writeId(XML_headers);
380 
381  rStrm.WriteAttributes(
382  XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)),
383  FSNS(XML_xmlns, XML_r), rStrm.getNamespaceURL(OOX_NS(officeRel)),
384  XML_guid, lcl_GuidToOString(maGUID),
385  XML_lastGuid, nullptr, // OOXTODO
386  XML_shared, nullptr, // OOXTODO
387  XML_diskRevisions, nullptr, // OOXTODO
388  XML_history, nullptr, // OOXTODO
389  XML_trackRevisions, nullptr, // OOXTODO
390  XML_exclusive, nullptr, // OOXTODO
391  XML_revisionId, nullptr, // OOXTODO
392  XML_version, nullptr, // OOXTODO
393  XML_keepChangeHistory, nullptr, // OOXTODO
394  XML_protected, nullptr, // OOXTODO
395  XML_preserveHistory, nullptr); // OOXTODO
396 
397  pHeaders->write(">");
398 }
399 
401  const OUString& rUserName, const DateTime& rDateTime, const sal_uInt8* pGUID,
402  sal_Int32 nLogNumber, const XclExpChTrTabIdBuffer& rBuf ) :
403  maUserName(rUserName), maDateTime(rDateTime), mnLogNumber(nLogNumber),
404  mnMinAction(0), mnMaxAction(0)
405 {
406  memcpy(maGUID, pGUID, 16);
407  if (rBuf.GetBufferCount())
408  {
409  maTabBuffer.resize(rBuf.GetBufferCount());
410  rBuf.GetBufferCopy(maTabBuffer.data());
411  }
412 }
413 
415 {
417 
418  pHeader->write("<")->writeId(XML_header);
419 
420  OUString aRelId;
422  XclXmlUtils::GetStreamName("xl/revisions/", "revisionLog", mnLogNumber),
423  XclXmlUtils::GetStreamName(nullptr, "revisionLog", mnLogNumber),
424  rStrm.GetCurrentStream()->getOutputStream(),
425  "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml",
426  CREATE_OFFICEDOC_RELATION_TYPE("revisionLog"),
427  &aRelId);
428 
429  rStrm.WriteAttributes(
430  XML_guid, lcl_GuidToOString(maGUID),
431  XML_dateTime, lcl_DateTimeToOString(maDateTime),
432  XML_userName, maUserName,
433  FSNS(XML_r, XML_id), aRelId);
434 
435  if (mnMinAction)
436  rStrm.WriteAttributes(XML_minRId, OUString::number(mnMinAction));
437 
438  if (mnMaxAction)
439  rStrm.WriteAttributes(XML_maxRId, OUString::number(mnMaxAction));
440 
441  if (!maTabBuffer.empty())
442  // next available sheet index.
443  rStrm.WriteAttributes(XML_maxSheetId, OUString::number(maTabBuffer.back()+1));
444 
445  pHeader->write(">");
446 
447  if (!maTabBuffer.empty())
448  {
449  // Write sheet index map.
450  size_t n = maTabBuffer.size();
451  pHeader->startElement(XML_sheetIdMap, XML_count, OString::number(n));
452 
453  for (size_t i = 0; i < n; ++i)
454  {
455  pHeader->singleElement(XML_sheetId, XML_val, OString::number(maTabBuffer[i]));
456  }
457  pHeader->endElement(XML_sheetIdMap);
458  }
459 
460  // Write all revision logs in a separate stream.
461 
462  rStrm.PushStream(pRevLogStrm);
463 
464  pRevLogStrm->write("<")->writeId(XML_revisions);
465 
466  rStrm.WriteAttributes(
467  XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)),
468  FSNS(XML_xmlns, XML_r), rStrm.getNamespaceURL(OOX_NS(officeRel)));
469 
470  pRevLogStrm->write(">");
471 
472  for (const auto& rxAction : maActions)
473  {
474  rxAction->SaveXml(rStrm);
475  }
476 
477  pRevLogStrm->write("</")->writeId(XML_revisions)->write(">");
478 
479  rStrm.PopStream();
480 
481  pHeader->write("</")->writeId(XML_header)->write(">");
482 }
483 
484 void XclExpXmlChTrHeader::AppendAction( std::unique_ptr<XclExpChTrAction> pAction )
485 {
486  sal_uInt32 nActionNum = pAction->GetActionNumber();
487  if (!mnMinAction || mnMinAction > nActionNum)
488  mnMinAction = nActionNum;
489 
490  if (!mnMaxAction || mnMaxAction < nActionNum)
491  mnMaxAction = nActionNum;
492 
493  maActions.push_back(std::move(pAction));
494 }
495 
496 XclExpChTrInfo::XclExpChTrInfo( const OUString& rUsername, const DateTime& rDateTime, const sal_uInt8* pGUID ) :
497  sUsername( rUsername ),
498  aDateTime( rDateTime )
499 {
500  memcpy( aGUID, pGUID, 16 );
501 }
502 
504 {
505 }
506 
508 {
509  rStrm << sal_uInt32(0xFFFFFFFF)
510  << sal_uInt32(0x00000000)
511  << sal_uInt32(0x00000020)
512  << sal_uInt16(0xFFFF);
513  lcl_WriteGUID( rStrm, aGUID );
514  rStrm << sal_uInt16(0x04B0);
515  lcl_WriteFixedString( rStrm, sUsername, 113 );
516  lcl_WriteDateTime( rStrm, aDateTime );
517  rStrm << sal_uInt8(0x0000)
518  << sal_uInt16(0x0002);
519 }
520 
521 sal_uInt16 XclExpChTrInfo::GetNum() const
522 {
523  return 0x0138;
524 }
525 
526 std::size_t XclExpChTrInfo::GetLen() const
527 {
528  return 158;
529 }
530 
532  nBufSize( nCount ),
533  nLastId( nCount )
534 {
535  pBuffer.reset( new sal_uInt16[ nBufSize ] );
536  memset( pBuffer.get(), 0, sizeof(sal_uInt16) * nBufSize );
537  pLast = pBuffer.get() + nBufSize - 1;
538 }
539 
541  nBufSize( rCopy.nBufSize ),
542  nLastId( rCopy.nLastId )
543 {
544  pBuffer.reset( new sal_uInt16[ nBufSize ] );
545  memcpy( pBuffer.get(), rCopy.pBuffer.get(), sizeof(sal_uInt16) * nBufSize );
546  pLast = pBuffer.get() + nBufSize - 1;
547 }
548 
550 {
551 }
552 
553 void XclExpChTrTabIdBuffer::InitFill( sal_uInt16 nIndex )
554 {
555  OSL_ENSURE( nIndex < nLastId, "XclExpChTrTabIdBuffer::Insert - out of range" );
556 
557  sal_uInt16 nFreeCount = 0;
558  for( sal_uInt16* pElem = pBuffer.get(); pElem <= pLast; pElem++ )
559  {
560  if( !*pElem )
561  nFreeCount++;
562  if( nFreeCount > nIndex )
563  {
564  *pElem = nLastId--;
565  return;
566  }
567  }
568 }
569 
571 {
572  sal_uInt16 nFreeCount = 1;
573  for( sal_uInt16* pElem = pBuffer.get(); pElem <= pLast; pElem++ )
574  if( !*pElem )
575  *pElem = nFreeCount++;
576  nLastId = nBufSize;
577 }
578 
579 sal_uInt16 XclExpChTrTabIdBuffer::GetId( sal_uInt16 nIndex ) const
580 {
581  OSL_ENSURE( nIndex < nBufSize, "XclExpChTrTabIdBuffer::GetId - out of range" );
582  return pBuffer[ nIndex ];
583 }
584 
586 {
587  OSL_ENSURE( pBuffer.get() <= pLast, "XclExpChTrTabIdBuffer::Remove - buffer empty" );
588  sal_uInt16* pElem = pBuffer.get();
589  while( (pElem <= pLast) && (*pElem != nLastId) )
590  pElem++;
591  while( pElem < pLast )
592  {
593  *pElem = *(pElem + 1);
594  pElem++;
595  }
596  pLast--;
597  nLastId--;
598 }
599 
601  : nTabCount( rBuffer.GetBufferCount() )
602 {
603  pBuffer.reset( new sal_uInt16[ nTabCount ] );
604  rBuffer.GetBufferCopy( pBuffer.get() );
605 }
606 
608 {
609  Clear();
610 }
611 
613 {
614  Clear();
615  nTabCount = rBuffer.GetBufferCount();
616  pBuffer.reset( new sal_uInt16[ nTabCount ] );
617  rBuffer.GetBufferCopy( pBuffer.get() );
618 }
619 
621 {
622  rStrm.EnableEncryption();
623  if( pBuffer )
624  rStrm.Write(pBuffer.get(), nTabCount);
625  else
626  for( sal_uInt16 nIndex = 1; nIndex <= nTabCount; nIndex++ )
627  rStrm << nIndex;
628 }
629 
630 sal_uInt16 XclExpChTrTabId::GetNum() const
631 {
632  return 0x013D;
633 }
634 
635 std::size_t XclExpChTrTabId::GetLen() const
636 {
637  return nTabCount << 1;
638 }
639 
640 // ! does not copy additional actions
642  ExcRecord( rCopy ),
643  sUsername( rCopy.sUsername ),
644  aDateTime( rCopy.aDateTime ),
645  nIndex( 0 ),
646  bAccepted( rCopy.bAccepted ),
647  rTabInfo( rCopy.rTabInfo ),
648  rIdBuffer( rCopy.rIdBuffer ),
649  nLength( rCopy.nLength ),
650  nOpCode( rCopy.nOpCode ),
651  bForceInfo( rCopy.bForceInfo )
652 {
653 }
654 
656  const ScChangeAction& rAction,
657  const XclExpRoot& rRoot,
658  const XclExpChTrTabIdBuffer& rTabIdBuffer,
659  sal_uInt16 nNewOpCode ) :
660  sUsername( rAction.GetUser() ),
661  aDateTime( rAction.GetDateTime() ),
662  nIndex( 0 ),
663  bAccepted( rAction.IsAccepted() ),
664  rTabInfo( rRoot.GetTabInfo() ),
665  rIdBuffer( rTabIdBuffer ),
666  nLength( 0 ),
667  nOpCode( nNewOpCode ),
668  bForceInfo( false )
669 {
670  aDateTime.SetSec( 0 );
671  aDateTime.SetNanoSec( 0 );
672 }
673 
675 {
676 }
677 
679 {
680  if( pAddAction )
681  pAddAction->SetAddAction( pAction );
682  else
683  pAddAction.reset( pAction );
684 }
685 
687  const ScChangeAction& rAction,
688  const XclExpRoot& rRoot,
689  const ScChangeTrack& rChangeTrack )
690 {
691  ScChangeActionMap aActionMap;
692 
693  rChangeTrack.GetDependents( const_cast<ScChangeAction*>(&rAction), aActionMap );
694  for( const auto& rEntry : aActionMap )
695  if( rEntry.second->GetType() == SC_CAT_CONTENT )
697  *static_cast<const ScChangeActionContent*>(rEntry.second), rRoot, rIdBuffer ) );
698 }
699 
700 void XclExpChTrAction::SetIndex( sal_uInt32& rIndex )
701 {
702  nIndex = rIndex++;
703 }
704 
706 {
707  OSL_ENSURE( nOpCode != EXC_CHTR_OP_UNKNOWN, "XclExpChTrAction::SaveCont - unknown action" );
708  rStrm << nLength
709  << nIndex
710  << nOpCode
711  << static_cast<sal_uInt16>(bAccepted ? EXC_CHTR_ACCEPT : EXC_CHTR_NOTHING);
712  SaveActionData( rStrm );
713 }
714 
716 {
717 }
718 
720 {
721 }
722 
724 {
725  PrepareSaveAction( rStrm );
726  ExcRecord::Save( rStrm );
727  if( pAddAction )
728  pAddAction->Save( rStrm );
729  CompleteSaveAction( rStrm );
730 }
731 
732 std::size_t XclExpChTrAction::GetLen() const
733 {
735 }
736 
738  mpFormulaCell( nullptr ),
739  fValue( 0.0 ),
740  nRKValue( 0 ),
742  nSize( 0 )
743 {
744 }
745 
747 {
748  Clear();
749 }
750 
752 {
753  pString.reset();
754  mpFormulaCell = nullptr;
755  mxTokArr.reset();
756  maRefLog.clear();
757  fValue = 0.0;
758  nRKValue = 0;
760  nSize = 0;
761 }
762 
764 {
765  OSL_ENSURE( mxTokArr && !mxTokArr->Empty(), "XclExpChTrData::Write - no formula" );
766  rStrm << *mxTokArr;
767 
768  for( const auto& rLogEntry : maRefLog )
769  {
770  if( rLogEntry.mpUrl && rLogEntry.mpFirstTab )
771  {
772  rStrm << *rLogEntry.mpUrl << sal_uInt8(0x01) << *rLogEntry.mpFirstTab << sal_uInt8(0x02);
773  }
774  else
775  {
776  bool bSingleTab = rLogEntry.mnFirstXclTab == rLogEntry.mnLastXclTab;
777  rStrm.SetSliceSize( bSingleTab ? 6 : 8 );
778  rStrm << sal_uInt8(0x01) << sal_uInt8(0x02) << sal_uInt8(0x00);
779  rStrm << rTabIdBuffer.GetId( rLogEntry.mnFirstXclTab );
780  if( bSingleTab )
781  rStrm << sal_uInt8(0x02);
782  else
783  rStrm << sal_uInt8(0x00) << rTabIdBuffer.GetId( rLogEntry.mnLastXclTab );
784  }
785  }
786  rStrm.SetSliceSize( 0 );
787  rStrm << sal_uInt8(0x00);
788 }
789 
790 void XclExpChTrData::Write( XclExpStream& rStrm, const XclExpChTrTabIdBuffer& rTabIdBuffer )
791 {
792  switch( nType )
793  {
794  case EXC_CHTR_TYPE_RK:
795  rStrm << nRKValue;
796  break;
798  rStrm << fValue;
799  break;
801  OSL_ENSURE( pString, "XclExpChTrData::Write - no string" );
802  rStrm << *pString;
803  break;
805  WriteFormula( rStrm, rTabIdBuffer );
806  break;
807  }
808 }
809 
811  const ScChangeActionContent& rAction,
812  const XclExpRoot& rRoot,
813  const XclExpChTrTabIdBuffer& rTabIdBuffer ) :
814  XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_CELL ),
815  XclExpRoot( rRoot ),
816  aPosition( rAction.GetBigRange().MakeRange().aStart )
817 {
818  sal_uInt32 nDummy32;
819  sal_uInt16 nDummy16;
820  GetCellData( rRoot, rAction.GetOldCell(), pOldData, nDummy32, nOldLength );
821  GetCellData( rRoot, rAction.GetNewCell(), pNewData, nLength, nDummy16 );
822 }
823 
825 {
826  pOldData.reset();
827  pNewData.reset();
828 }
829 
830 void XclExpChTrCellContent::MakeEmptyChTrData( std::unique_ptr<XclExpChTrData>& rpData )
831 {
832  if( rpData )
833  rpData->Clear();
834  else
835  rpData.reset( new XclExpChTrData );
836 }
837 
839  const XclExpRoot& rRoot, const ScCellValue& rScCell,
840  std::unique_ptr<XclExpChTrData>& rpData, sal_uInt32& rXclLength1, sal_uInt16& rXclLength2 )
841 {
842  MakeEmptyChTrData( rpData );
843  rXclLength1 = 0x0000003A;
844  rXclLength2 = 0x0000;
845 
846  if (rScCell.isEmpty())
847  {
848  rpData.reset();
849  return;
850  }
851 
852  switch (rScCell.meType)
853  {
854  case CELLTYPE_VALUE:
855  {
856  rpData->fValue = rScCell.mfValue;
857  if( XclTools::GetRKFromDouble( rpData->nRKValue, rpData->fValue ) )
858  {
859  rpData->nType = EXC_CHTR_TYPE_RK;
860  rpData->nSize = 4;
861  rXclLength1 = 0x0000003E;
862  rXclLength2 = 0x0004;
863  }
864  else
865  {
866  rpData->nType = EXC_CHTR_TYPE_DOUBLE;
867  rpData->nSize = 8;
868  rXclLength1 = 0x00000042;
869  rXclLength2 = 0x0008;
870  }
871  }
872  break;
873  case CELLTYPE_STRING:
874  case CELLTYPE_EDIT:
875  {
876  OUString sCellStr;
877  if (rScCell.meType == CELLTYPE_STRING)
878  {
879  sCellStr = rScCell.mpString->getString();
880  rpData->mpFormattedString = XclExpStringHelper::CreateCellString(
881  rRoot, sCellStr, nullptr);
882  }
883  else
884  {
885  XclExpHyperlinkHelper aLinkHelper( rRoot, aPosition );
886  if (rScCell.mpEditText)
887  {
888  sCellStr = ScEditUtil::GetString(*rScCell.mpEditText, &GetDoc());
889  rpData->mpFormattedString = XclExpStringHelper::CreateCellString(
890  rRoot, *rScCell.mpEditText, nullptr, aLinkHelper);
891  }
892  else
893  {
894  rpData->mpFormattedString = XclExpStringHelper::CreateCellString(
895  rRoot, EMPTY_OUSTRING, nullptr);
896  }
897  }
898  rpData->pString.reset( new XclExpString( sCellStr, XclStrFlags::NONE, 32766 ) );
899  rpData->nType = EXC_CHTR_TYPE_STRING;
900  rpData->nSize = 3 + rpData->pString->GetSize();
901  rXclLength1 = 64 + (sCellStr.getLength() << 1);
902  rXclLength2 = 6 + static_cast<sal_uInt16>(sCellStr.getLength() << 1);
903  }
904  break;
905  case CELLTYPE_FORMULA:
906  {
907  const ScFormulaCell* pFmlCell = rScCell.mpFormula;
908  rpData->mpFormulaCell = pFmlCell;
909 
910  const ScTokenArray* pTokenArray = pFmlCell->GetCode();
911  if( pTokenArray )
912  {
913  XclExpRefLog& rRefLog = rpData->maRefLog;
914  rpData->mxTokArr = GetFormulaCompiler().CreateFormula(
915  EXC_FMLATYPE_CELL, *pTokenArray, &pFmlCell->aPos, &rRefLog );
916  rpData->nType = EXC_CHTR_TYPE_FORMULA;
917  std::size_t nSize = std::accumulate(rRefLog.begin(), rRefLog.end(),
918  static_cast<std::size_t>(rpData->mxTokArr->GetSize() + 3),
919  [](const std::size_t& rSum, const XclExpRefLogEntry& rLogEntry) {
920  if( rLogEntry.mpUrl && rLogEntry.mpFirstTab )
921  return rSum + rLogEntry.mpUrl->GetSize() + rLogEntry.mpFirstTab->GetSize() + 2;
922  else
923  return rSum + ((rLogEntry.mnFirstXclTab == rLogEntry.mnLastXclTab) ? 6 : 8);
924  });
925  rpData->nSize = ::std::min< std::size_t >( nSize, 0xFFFF );
926  rXclLength1 = 0x00000052;
927  rXclLength2 = 0x0018;
928  }
929  }
930  break;
931  default:;
932  }
933 }
934 
936 {
937  WriteTabId( rStrm, aPosition.Tab() );
938  rStrm << static_cast<sal_uInt16>((pOldData ? (pOldData->nType << 3) : 0x0000) | (pNewData ? pNewData->nType : 0x0000))
939  << sal_uInt16(0x0000);
940  Write2DAddress( rStrm, aPosition );
941  rStrm << nOldLength
942  << sal_uInt32(0x00000000);
943  if( pOldData )
944  pOldData->Write( rStrm, rIdBuffer );
945  if( pNewData )
946  pNewData->Write( rStrm, rIdBuffer );
947 }
948 
950 {
951  return 0x013B;
952 }
953 
955 {
956  std::size_t nLen = 16;
957  if( pOldData )
958  nLen += pOldData->nSize;
959  if( pNewData )
960  nLen += pNewData->nSize;
961  return nLen;
962 }
963 
964 static const char* lcl_GetType( XclExpChTrData* pData )
965 {
966  switch( pData->nType )
967  {
968  case EXC_CHTR_TYPE_RK:
970  return "n";
971  break;
973  {
974  ScFormulaCell* pFormulaCell = const_cast< ScFormulaCell* >( pData->mpFormulaCell );
975  const char* sType;
976  OUString sValue;
977  XclXmlUtils::GetFormulaTypeAndValue( *pFormulaCell, sType, sValue );
978  return sType;
979  }
980  break;
982  return "inlineStr";
983  break;
984  default:
985  break;
986  }
987  return "*unknown*";
988 }
989 
990 static void lcl_WriteCell( XclExpXmlStream& rStrm, sal_Int32 nElement, const ScAddress& rPosition, XclExpChTrData* pData )
991 {
993 
994  pStream->startElement(nElement,
995  XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), rPosition),
996  XML_s, nullptr, // OOXTODO: not supported
997  XML_t, lcl_GetType(pData),
998  XML_cm, nullptr, // OOXTODO: not supported
999  XML_vm, nullptr, // OOXTODO: not supported
1000  XML_ph, nullptr); // OOXTODO: not supported
1001  switch( pData->nType )
1002  {
1003  case EXC_CHTR_TYPE_RK:
1004  case EXC_CHTR_TYPE_DOUBLE:
1005  pStream->startElement(XML_v);
1006  pStream->write( pData->fValue );
1007  pStream->endElement( XML_v );
1008  break;
1009  case EXC_CHTR_TYPE_FORMULA:
1010  pStream->startElement( XML_f
1011  // OOXTODO: other attributes? see XclExpFormulaCell::SaveXml()
1012  );
1013  pStream->writeEscaped( XclXmlUtils::ToOUString(
1015  pData->mpFormulaCell->aPos, pData->mpFormulaCell->GetCode()));
1016  pStream->endElement( XML_f );
1017  break;
1018  case EXC_CHTR_TYPE_STRING:
1019  pStream->startElement(XML_is);
1020  if( pData->mpFormattedString )
1021  pData->mpFormattedString->WriteXml( rStrm );
1022  else
1023  pData->pString->WriteXml( rStrm );
1024  pStream->endElement( XML_is );
1025  break;
1026  default:
1027  // ignore
1028  break;
1029  }
1030  pStream->endElement( nElement );
1031 }
1032 
1034 {
1035  sax_fastparser::FSHelperPtr pStream = rRevisionLogStrm.GetCurrentStream();
1036  pStream->startElement( XML_rcc,
1037  XML_rId, OString::number(GetActionNumber()),
1038  XML_ua, ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1039  XML_ra, nullptr, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1040  XML_sId, OString::number(GetTabId(aPosition.Tab())),
1041  XML_odxf, nullptr, // OOXTODO: not supported
1042  XML_xfDxf, nullptr, // OOXTODO: not supported
1043  XML_s, nullptr, // OOXTODO: not supported
1044  XML_dxf, nullptr, // OOXTODO: not supported
1045  XML_numFmtId, nullptr, // OOXTODO: not supported
1046  XML_quotePrefix, nullptr, // OOXTODO: not supported
1047  XML_oldQuotePrefix, nullptr, // OOXTODO: not supported
1048  XML_ph, nullptr, // OOXTODO: not supported
1049  XML_oldPh, nullptr, // OOXTODO: not supported
1050  XML_endOfListFormulaUpdate, nullptr); // OOXTODO: not supported
1051  if( pOldData )
1052  {
1053  lcl_WriteCell( rRevisionLogStrm, XML_oc, aPosition, pOldData.get() );
1054  if (!pNewData)
1055  {
1056  pStream->singleElement(XML_nc, XML_r, XclXmlUtils::ToOString(rRevisionLogStrm.GetRoot().GetDoc(), aPosition));
1057  }
1058  }
1059  if( pNewData )
1060  {
1061  lcl_WriteCell( rRevisionLogStrm, XML_nc, aPosition, pNewData.get() );
1062  }
1063  // OOXTODO: XML_odxf, XML_ndxf, XML_extLst elements
1064  pStream->endElement( XML_rcc );
1065 }
1066 
1068  XclExpChTrAction(rCopy),
1069  mbEndOfList(rCopy.mbEndOfList),
1070  aRange(rCopy.aRange) {}
1071 
1073  const ScChangeAction& rAction,
1074  const XclExpRoot& rRoot,
1075  const XclExpChTrTabIdBuffer& rTabIdBuffer,
1076  const ScChangeTrack& rChangeTrack ) :
1077  XclExpChTrAction( rAction, rRoot, rTabIdBuffer ),
1078  mbEndOfList(false),
1079  aRange( rAction.GetBigRange().MakeRange() )
1080 {
1081  nLength = 0x00000030;
1082  switch( rAction.GetType() )
1083  {
1085  case SC_CAT_INSERT_ROWS:
1086  {
1087  const ScChangeActionIns& rIns = static_cast<const ScChangeActionIns&>(rAction);
1088  mbEndOfList = rIns.IsEndOfList();
1090  }
1091  break;
1094  default:
1095  OSL_FAIL( "XclExpChTrInsert::XclExpChTrInsert - unknown action" );
1096  }
1097 
1099  {
1100  aRange.aStart.SetRow( 0 );
1101  aRange.aEnd.SetRow( rRoot.GetXclMaxPos().Row() );
1102  }
1103  else
1104  {
1105  aRange.aStart.SetCol( 0 );
1106  aRange.aEnd.SetCol( rRoot.GetXclMaxPos().Col() );
1107  }
1108 
1110  {
1111  SetAddAction( new XclExpChTr0x014A( *this ) );
1112  AddDependentContents( rAction, rRoot, rChangeTrack );
1113  }
1114 }
1115 
1117 {
1118 }
1119 
1121 {
1122  WriteTabId( rStrm, aRange.aStart.Tab() );
1123  sal_uInt16 nFlagVal = mbEndOfList ? 0x0001 : 0x0000;
1124  rStrm << nFlagVal;
1125  Write2DRange( rStrm, aRange );
1126  rStrm << sal_uInt32(0x00000000);
1127 }
1128 
1130 {
1132  XclExpChTrEmpty( 0x0150 ).Save( rStrm );
1133 }
1134 
1136 {
1138  XclExpChTrEmpty( 0x0151 ).Save( rStrm );
1139 }
1140 
1141 sal_uInt16 XclExpChTrInsert::GetNum() const
1142 {
1143  return 0x0137;
1144 }
1145 
1147 {
1148  return 16;
1149 }
1150 
1151 static const char* lcl_GetAction( sal_uInt16 nOpCode )
1152 {
1153  switch( nOpCode )
1154  {
1155  case EXC_CHTR_OP_INSCOL: return "insertCol";
1156  case EXC_CHTR_OP_INSROW: return "insertRow";
1157  case EXC_CHTR_OP_DELCOL: return "deleteCol";
1158  case EXC_CHTR_OP_DELROW: return "deleteRow";
1159  default: return "*unknown*";
1160  }
1161 }
1162 
1164 {
1165  sax_fastparser::FSHelperPtr pStream = rRevisionLogStrm.GetCurrentStream();
1166  pStream->startElement( XML_rrc,
1167  XML_rId, OString::number(GetActionNumber()),
1168  XML_ua, ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1169  XML_ra, nullptr, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1170  XML_sId, OString::number(GetTabId(aRange.aStart.Tab())),
1171  XML_eol, ToPsz10(mbEndOfList),
1172  XML_ref, XclXmlUtils::ToOString(rRevisionLogStrm.GetRoot().GetDoc(), aRange),
1173  XML_action, lcl_GetAction( nOpCode ),
1174  XML_edge, nullptr); // OOXTODO: ???
1175 
1176  // OOXTODO: does this handle XML_rfmt, XML_undo?
1177  XclExpChTrAction* pAction = GetAddAction();
1178  while( pAction != nullptr )
1179  {
1180  pAction->SaveXml( rRevisionLogStrm );
1181  pAction = pAction->GetAddAction();
1182  }
1183  pStream->endElement( XML_rrc );
1184 }
1185 
1187  const ScChangeAction& rAction,
1188  const XclExpRoot& rRoot,
1189  const XclExpChTrTabIdBuffer& rTabIdBuffer ) :
1190  XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_INSTAB ),
1191  XclExpRoot( rRoot ),
1192  nTab( static_cast<SCTAB>(rAction.GetBigRange().aStart.Tab()) )
1193 {
1194  nLength = 0x0000021C;
1195  bForceInfo = true;
1196 }
1197 
1199 {
1200 }
1201 
1203 {
1204  WriteTabId( rStrm, nTab );
1205  rStrm << sal_uInt32( 0 );
1206  lcl_WriteFixedString( rStrm, XclExpString( GetTabInfo().GetScTabName( nTab ) ), 127 );
1207  lcl_WriteDateTime( rStrm, GetDateTime() );
1208  rStrm.WriteZeroBytes( 133 );
1209 }
1210 
1212 {
1213  return 0x014D;
1214 }
1215 
1217 {
1218  return 276;
1219 }
1220 
1222 {
1224  pStream->singleElement( XML_ris,
1225  XML_rId, OString::number(GetActionNumber()),
1226  XML_ua, ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1227  XML_ra, nullptr, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1228  XML_sheetId, OString::number(GetTabId(nTab)),
1229  XML_name, GetTabInfo().GetScTabName(nTab).toUtf8(),
1230  XML_sheetPosition, OString::number(nTab) );
1231 }
1232 
1234  const ScChangeActionMove& rAction,
1235  const XclExpRoot& rRoot,
1236  const XclExpChTrTabIdBuffer& rTabIdBuffer,
1237  const ScChangeTrack& rChangeTrack ) :
1238  XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_MOVE ),
1239  aDestRange( rAction.GetBigRange().MakeRange() )
1240 {
1241  nLength = 0x00000042;
1243  sal_Int32 nDCols, nDRows, nDTabs;
1244  rAction.GetDelta( nDCols, nDRows, nDTabs );
1245  aSourceRange.aStart.IncRow( static_cast<SCROW>(-nDRows) );
1246  aSourceRange.aStart.IncCol( static_cast<SCCOL>(-nDCols) );
1247  aSourceRange.aStart.IncTab( static_cast<SCTAB>(-nDTabs) );
1248  aSourceRange.aEnd.IncRow( static_cast<SCROW>(-nDRows) );
1249  aSourceRange.aEnd.IncCol( static_cast<SCCOL>(-nDCols) );
1250  aSourceRange.aEnd.IncTab( static_cast<SCTAB>(-nDTabs) );
1251  AddDependentContents( rAction, rRoot, rChangeTrack );
1252 }
1253 
1255 {
1256 }
1257 
1259 {
1260  WriteTabId( rStrm, aDestRange.aStart.Tab() );
1261  Write2DRange( rStrm, aSourceRange );
1262  Write2DRange( rStrm, aDestRange );
1263  WriteTabId( rStrm, aSourceRange.aStart.Tab() );
1264  rStrm << sal_uInt32(0x00000000);
1265 }
1266 
1268 {
1269  XclExpChTrEmpty( 0x014E ).Save( rStrm );
1270 }
1271 
1273 {
1274  XclExpChTrEmpty( 0x014F ).Save( rStrm );
1275 }
1276 
1278 {
1279  return 0x0140;
1280 }
1281 
1283 {
1284  return 24;
1285 }
1286 
1288 {
1289  sax_fastparser::FSHelperPtr pStream = rRevisionLogStrm.GetCurrentStream();
1290 
1291  pStream->startElement( XML_rm,
1292  XML_rId, OString::number(GetActionNumber()),
1293  XML_ua, ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1294  XML_ra, nullptr, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1295  XML_sheetId, OString::number(GetTabId(aDestRange.aStart.Tab())),
1296  XML_source, XclXmlUtils::ToOString(rRevisionLogStrm.GetRoot().GetDoc(), aSourceRange),
1297  XML_destination, XclXmlUtils::ToOString(rRevisionLogStrm.GetRoot().GetDoc(), aDestRange),
1298  XML_sourceSheetId, OString::number(GetTabId(aSourceRange.aStart.Tab())) );
1299  // OOXTODO: does this handle XML_rfmt, XML_undo?
1300  XclExpChTrAction* pAction = GetAddAction();
1301  while( pAction != nullptr )
1302  {
1303  pAction->SaveXml( rRevisionLogStrm );
1304  pAction = pAction->GetAddAction();
1305  }
1306  pStream->endElement( XML_rm );
1307 }
1308 
1310  XclExpChTrInsert( rAction )
1311 {
1312  nLength = 0x00000026;
1314 }
1315 
1317 {
1318 }
1319 
1321 {
1322  WriteTabId( rStrm, aRange.aStart.Tab() );
1323  rStrm << sal_uInt16(0x0003)
1324  << sal_uInt16(0x0001);
1325  Write2DRange( rStrm, aRange );
1326 }
1327 
1328 sal_uInt16 XclExpChTr0x014A::GetNum() const
1329 {
1330  return 0x014A;
1331 }
1332 
1334 {
1335  return 14;
1336 }
1337 
1339 {
1341 
1342  pStream->startElement( XML_rfmt,
1343  XML_sheetId, OString::number(GetTabId(aRange.aStart.Tab())),
1344  XML_xfDxf, nullptr, // OOXTODO: not supported
1345  XML_s, nullptr, // OOXTODO: style
1346  XML_sqref, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aRange),
1347  XML_start, nullptr, // OOXTODO: for string changes
1348  XML_length, nullptr); // OOXTODO: for string changes
1349  // OOXTODO: XML_dxf, XML_extLst
1350 
1351  pStream->endElement( XML_rfmt );
1352 }
1353 
1354 std::size_t ExcXmlRecord::GetLen() const
1355 {
1356  return 0;
1357 }
1358 
1359 sal_uInt16 ExcXmlRecord::GetNum() const
1360 {
1361  return 0;
1362 }
1363 
1365 {
1366  // Do nothing; ignored for BIFF output.
1367 }
1368 
1369 namespace {
1370 
1371 class EndXmlElement : public ExcXmlRecord
1372 {
1373  sal_Int32 mnElement;
1374 public:
1375  explicit EndXmlElement( sal_Int32 nElement ) : mnElement( nElement) {}
1376  virtual void SaveXml( XclExpXmlStream& rStrm ) override;
1377 };
1378 
1379 }
1380 
1381 void EndXmlElement::SaveXml( XclExpXmlStream& rStrm )
1382 {
1384  pStream->write("</")->writeId(mnElement)->write(">");
1385 }
1386 
1388  XclExpRoot( rRoot ),
1389  aActionStack(),
1390  pTabIdBuffer( nullptr )
1391 {
1392  OSL_ENSURE( GetOldRoot().pTabId, "XclExpChangeTrack::XclExpChangeTrack - root data incomplete" );
1393  if( !GetOldRoot().pTabId )
1394  return;
1395 
1396  ScChangeTrack* pTempChangeTrack = CreateTempChangeTrack();
1397  if (!pTempChangeTrack)
1398  return;
1399 
1400  pTabIdBuffer = new XclExpChTrTabIdBuffer( GetTabInfo().GetXclTabCount() );
1401  maBuffers.push_back( std::unique_ptr<XclExpChTrTabIdBuffer>(pTabIdBuffer) );
1402 
1403  // calculate final table order (tab id list)
1404  const ScChangeAction* pScAction;
1405  for( pScAction = pTempChangeTrack->GetLast(); pScAction; pScAction = pScAction->GetPrev() )
1406  {
1407  if( pScAction->GetType() == SC_CAT_INSERT_TABS )
1408  {
1409  SCTAB nScTab = static_cast< SCTAB >( pScAction->GetBigRange().aStart.Tab() );
1410  pTabIdBuffer->InitFill( GetTabInfo().GetXclTab( nScTab ) );
1411  }
1412  }
1415 
1416  // get actions in reverse order
1417  pScAction = pTempChangeTrack->GetLast();
1418  while( pScAction )
1419  {
1420  PushActionRecord( *pScAction );
1421  const ScChangeAction* pPrevAction = pScAction->GetPrev();
1422  pScAction = pPrevAction;
1423  }
1424 
1425  // build record list
1426  if (GetOutput() == EXC_OUTPUT_BINARY)
1427  {
1428  XclExpChTrHeader* pHeader = new XclExpChTrHeader; // header record for last GUID
1429  maRecList.push_back( std::unique_ptr<ExcRecord>(pHeader) );
1430  maRecList.push_back( std::unique_ptr<ExcRecord>( new XclExpChTr0x0195 ) );
1431  maRecList.push_back( std::unique_ptr<ExcRecord>( new XclExpChTr0x0194( *pTempChangeTrack ) ) );
1432 
1433  OUString sLastUsername;
1434  DateTime aLastDateTime( DateTime::EMPTY );
1435  sal_uInt32 nIndex = 1;
1436  sal_Int32 nLogNumber = 1;
1437  sal_uInt8 aGUID[ 16 ]; // GUID for action info records
1438  bool bValidGUID = false;
1439  while( !aActionStack.empty() )
1440  {
1441  XclExpChTrAction* pAction = aActionStack.top();
1442  aActionStack.pop();
1443 
1444  if( (nIndex == 1) || pAction->ForceInfoRecord() ||
1445  (pAction->GetUsername() != sLastUsername) ||
1446  (pAction->GetDateTime() != aLastDateTime) )
1447  {
1448  lcl_GenerateGUID( aGUID, bValidGUID );
1449  sLastUsername = pAction->GetUsername();
1450  aLastDateTime = pAction->GetDateTime();
1451 
1452  nLogNumber++;
1453  maRecList.push_back( std::unique_ptr<ExcRecord>(new XclExpChTrInfo(sLastUsername, aLastDateTime, aGUID)) );
1454  maRecList.push_back( std::unique_ptr<ExcRecord>(new XclExpChTrTabId(pAction->GetTabIdBuffer())) );
1455  pHeader->SetGUID( aGUID );
1456  }
1457  pAction->SetIndex( nIndex );
1458  maRecList.push_back( std::unique_ptr<ExcRecord>(pAction) );
1459  }
1460 
1461  pHeader->SetGUID( aGUID );
1462  pHeader->SetCount( nIndex - 1 );
1463  maRecList.push_back( std::unique_ptr<ExcRecord>(new ExcEof) );
1464  }
1465  else
1466  {
1468  maRecList.push_back( std::unique_ptr<ExcRecord>(pHeaders));
1469 
1470  OUString sLastUsername;
1471  DateTime aLastDateTime(DateTime::EMPTY);
1472  sal_uInt32 nIndex = 1;
1473  sal_Int32 nLogNumber = 1;
1474  XclExpXmlChTrHeader* pCurHeader = nullptr;
1475  sal_uInt8 aGUID[ 16 ]; // GUID for action info records
1476  bool bValidGUID = false;
1477 
1478  while (!aActionStack.empty())
1479  {
1480  XclExpChTrAction* pAction = aActionStack.top();
1481  aActionStack.pop();
1482 
1483  if( (nIndex == 1) || pAction->ForceInfoRecord() ||
1484  (pAction->GetUsername() != sLastUsername) ||
1485  (pAction->GetDateTime() != aLastDateTime) )
1486  {
1487  lcl_GenerateGUID( aGUID, bValidGUID );
1488  sLastUsername = pAction->GetUsername();
1489  aLastDateTime = pAction->GetDateTime();
1490 
1491  pCurHeader = new XclExpXmlChTrHeader(sLastUsername, aLastDateTime, aGUID, nLogNumber, pAction->GetTabIdBuffer());
1492  maRecList.push_back( std::unique_ptr<ExcRecord>(pCurHeader));
1493  nLogNumber++;
1494  pHeaders->SetGUID(aGUID);
1495  }
1496  pAction->SetIndex(nIndex);
1497  pCurHeader->AppendAction(std::unique_ptr<XclExpChTrAction>(pAction));
1498  }
1499 
1500  pHeaders->SetGUID(aGUID);
1501  maRecList.push_back( std::unique_ptr<ExcRecord>(new EndXmlElement(XML_headers)));
1502  }
1503 }
1504 
1506 {
1507  while( !aActionStack.empty() )
1508  {
1509  delete aActionStack.top();
1510  aActionStack.pop();
1511  }
1512 }
1513 
1515 {
1516  // get original change track
1517  ScChangeTrack* pOrigChangeTrack = GetDoc().GetChangeTrack();
1518  OSL_ENSURE( pOrigChangeTrack, "XclExpChangeTrack::CreateTempChangeTrack - no change track data" );
1519  if( !pOrigChangeTrack )
1520  return nullptr;
1521 
1522  assert(!xTempDoc);
1523  // create empty document
1524  xTempDoc.reset(new ScDocument);
1525 
1526  // adjust table count
1527  SCTAB nOrigCount = GetDoc().GetTableCount();
1528  OUString sTabName;
1529  for( sal_Int32 nIndex = 0; nIndex < nOrigCount; nIndex++ )
1530  {
1531  xTempDoc->CreateValidTabName(sTabName);
1532  xTempDoc->InsertTab(SC_TAB_APPEND, sTabName);
1533  }
1534  OSL_ENSURE(nOrigCount == xTempDoc->GetTableCount(),
1535  "XclExpChangeTrack::CreateTempChangeTrack - table count mismatch");
1536  if(nOrigCount != xTempDoc->GetTableCount())
1537  return nullptr;
1538 
1539  return pOrigChangeTrack->Clone(xTempDoc.get());
1540 }
1541 
1543 {
1544  XclExpChTrAction* pXclAction = nullptr;
1545  ScChangeTrack* pTempChangeTrack = xTempDoc->GetChangeTrack();
1546  switch( rAction.GetType() )
1547  {
1548  case SC_CAT_CONTENT:
1549  pXclAction = new XclExpChTrCellContent( static_cast<const ScChangeActionContent&>(rAction), GetRoot(), *pTabIdBuffer );
1550  break;
1551  case SC_CAT_INSERT_ROWS:
1552  case SC_CAT_INSERT_COLS:
1553  case SC_CAT_DELETE_ROWS:
1554  case SC_CAT_DELETE_COLS:
1555  if (pTempChangeTrack)
1556  pXclAction = new XclExpChTrInsert( rAction, GetRoot(), *pTabIdBuffer, *pTempChangeTrack );
1557  break;
1558  case SC_CAT_INSERT_TABS:
1559  {
1560  pXclAction = new XclExpChTrInsertTab( rAction, GetRoot(), *pTabIdBuffer );
1562  pNewBuffer->Remove();
1563  maBuffers.push_back( std::unique_ptr<XclExpChTrTabIdBuffer>(pNewBuffer) );
1564  pTabIdBuffer = pNewBuffer;
1565  }
1566  break;
1567  case SC_CAT_MOVE:
1568  if (pTempChangeTrack)
1569  pXclAction = new XclExpChTrMoveRange( static_cast<const ScChangeActionMove&>(rAction), GetRoot(), *pTabIdBuffer, *pTempChangeTrack );
1570  break;
1571  default:;
1572  }
1573  if( pXclAction )
1574  aActionStack.push( pXclAction );
1575 }
1576 
1578 {
1579  bool bRet = false;
1581  OSL_ENSURE( xSvStrm.is(), "XclExpChangeTrack::WriteUserNamesStream - no stream" );
1582  if( xSvStrm.is() )
1583  {
1584  XclExpStream aXclStrm( *xSvStrm, GetRoot() );
1585  XclExpChTr0x0191().Save( aXclStrm );
1586  XclExpChTr0x0198().Save( aXclStrm );
1587  XclExpChTr0x0192().Save( aXclStrm );
1588  XclExpChTr0x0197().Save( aXclStrm );
1589  xSvStrm->Commit();
1590  bRet = true;
1591  }
1592  return bRet;
1593 }
1594 
1596 {
1597  if (maRecList.empty())
1598  return;
1599 
1600  if( !WriteUserNamesStream() )
1601  return;
1602 
1604  OSL_ENSURE( xSvStrm.is(), "XclExpChangeTrack::Write - no stream" );
1605  if( xSvStrm.is() )
1606  {
1607  XclExpStream aXclStrm( *xSvStrm, GetRoot(), EXC_MAXRECSIZE_BIFF8 + 8 );
1608 
1609  for(const auto& rxRec : maRecList)
1610  rxRec->Save(aXclStrm);
1611 
1612  xSvStrm->Commit();
1613  }
1614 }
1615 
1616 static void lcl_WriteUserNamesXml( XclExpXmlStream& rWorkbookStrm )
1617 {
1618  sax_fastparser::FSHelperPtr pUserNames = rWorkbookStrm.CreateOutputStream(
1619  "xl/revisions/userNames.xml",
1620  "revisions/userNames.xml",
1621  rWorkbookStrm.GetCurrentStream()->getOutputStream(),
1622  "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml",
1623  CREATE_OFFICEDOC_RELATION_TYPE("usernames"));
1624  pUserNames->startElement( XML_users,
1625  XML_xmlns, rWorkbookStrm.getNamespaceURL(OOX_NS(xls)).toUtf8(),
1626  FSNS( XML_xmlns, XML_r ), rWorkbookStrm.getNamespaceURL(OOX_NS(officeRel)).toUtf8(),
1627  XML_count, "0" );
1628  // OOXTODO: XML_userinfo elements for each user editing the file
1629  // Doesn't seem to be supported by .xls output either (based on
1630  // contents of XclExpChangeTrack::WriteUserNamesStream()).
1631  pUserNames->endElement( XML_users );
1632 }
1633 
1635 {
1636  if (maRecList.empty())
1637  return;
1638 
1639  lcl_WriteUserNamesXml( rWorkbookStrm );
1640 
1641  sax_fastparser::FSHelperPtr pRevisionHeaders = rWorkbookStrm.CreateOutputStream(
1642  "xl/revisions/revisionHeaders.xml",
1643  "revisions/revisionHeaders.xml",
1644  rWorkbookStrm.GetCurrentStream()->getOutputStream(),
1645  "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml",
1646  CREATE_OFFICEDOC_RELATION_TYPE("revisionHeaders"));
1647  // OOXTODO: XML_userinfo elements for each user editing the file
1648  // Doesn't seem to be supported by .xls output either (based on
1649  // contents of XclExpChangeTrack::WriteUserNamesStream()).
1650  rWorkbookStrm.PushStream( pRevisionHeaders );
1651 
1652  for (const auto& rxRec : maRecList)
1653  rxRec->SaveXml(rWorkbookStrm);
1654 
1655  rWorkbookStrm.PopStream();
1656 }
1657 
1658 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void AppendAction(std::unique_ptr< XclExpChTrAction > pAction)
void AddDependentContents(const ScChangeAction &rAction, const XclExpRoot &rRoot, const ScChangeTrack &rChangeTrack)
void WriteAttributes(sal_Int32 nAttribute, Str &&value, Args &&...rest)
Definition: xestream.hxx:299
virtual std::size_t GetActionByteCount() const override
bool is() const
This class stores an unformatted or formatted string for Excel export.
Definition: xestring.hxx:43
virtual std::size_t GetActionByteCount() const override
sal_uInt16 GetTabId(SCTAB nTabId) const
void SetGUID(const sal_uInt8 *pGUID)
virtual ~XclExpChTrTabId() override
std::unique_ptr< XclExpChTrData > pOldData
std::size_t Write(const void *pData, std::size_t nBytes)
Writes nBytes bytes from memory.
Definition: xestream.cxx:215
static void GetFormulaTypeAndValue(ScFormulaCell &rCell, const char *&sType, OUString &rValue)
Definition: xestream.cxx:657
virtual void SaveActionData(XclExpStream &rStrm) const override
static OString ToOString(const Color &rColor)
Definition: xestream.cxx:698
const ScCellValue & GetOldCell() const
Definition: chgtrack.hxx:746
virtual std::size_t GetLen() const override
static void lcl_WriteGUID(XclExpStream &rStrm, const sal_uInt8 *pGUID)
virtual ~XclExpChTrInsert() override
sal_Int32 nIndex
CellType meType
Definition: cellvalue.hxx:38
OUString getString() const
ScAddress aStart
Definition: address.hxx:500
virtual sal_uInt16 GetNum() const override
virtual void SaveCont(XclExpStream &rStrm) override
virtual sal_uInt16 GetNum() const override
ScChangeActionType GetType() const
Definition: chgtrack.hxx:318
std::unique_ptr< sal_uInt16[]> pBuffer
virtual std::size_t GetLen() const override
virtual ~XclExpChTrEmpty() override
#define EMPTY_OUSTRING
Definition: global.hxx:215
#define EXC_CHTR_TYPE_EMPTY
Definition: excdefs.hxx:81
const XclExpRoot & GetRoot() const
Returns the filter root data.
Definition: xestream.hxx:290
virtual void SaveXml(XclExpXmlStream &rStrm) override
void IncTab(SCTAB nDelta=1)
Definition: address.hxx:308
This class is used to export Excel record streams.
Definition: xestream.hxx:71
SCROW Row() const
Definition: address.hxx:262
virtual void SaveCont(XclExpStream &rStrm) override
#define EXC_CHTR_OP_DELFLAG
Definition: excdefs.hxx:67
virtual void SaveCont(XclExpStream &rStrm) override
void WriteFormula(XclExpStream &rStrm, const XclExpChTrTabIdBuffer &rTabIdBuffer)
void SetSec(sal_uInt16 nNewSec)
XclExpChTrCellContent(const ScChangeActionContent &rAction, const XclExpRoot &rRoot, const XclExpChTrTabIdBuffer &rTabIdBuffer)
virtual std::size_t GetLen() const override
XclExpChTrAction * GetAddAction()
virtual std::size_t GetActionByteCount() const override
virtual void SaveActionData(XclExpStream &rStrm) const override
virtual sal_uInt16 GetNum() const override
ScChangeAction * GetLast() const
Definition: chgtrack.hxx:960
virtual std::size_t GetLen() const override
virtual sal_uInt16 GetNum() const override
virtual void SaveCont(XclExpStream &rStrm) override
XclExpChTrTabIdBuffer * pTabIdBuffer
static OUString ToOUString(const char *s)
Definition: xestream.cxx:783
ScTokenArray * GetCode()
virtual ~XclExpChTrHeader() override
virtual void CompleteSaveAction(XclExpStream &rStrm) const override
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: excrecds.cxx:104
void GetCellData(const XclExpRoot &rRoot, const ScCellValue &rScCell, std::unique_ptr< XclExpChTrData > &rpData, sal_uInt32 &rXclLength1, sal_uInt16 &rXclLength2)
#define CREATE_OFFICEDOC_RELATION_TYPE(ascii)
sal_Int64 n
XclExpFormulaCompiler & GetFormulaCompiler() const
Returns the formula compiler to produce formula token arrays.
Definition: xeroot.cxx:87
#define EXC_CHTR_OP_INSTAB
Definition: excdefs.hxx:73
std::unique_ptr< sal_uInt16[]> pBuffer
virtual void SaveCont(XclExpStream &rStrm) override
virtual sal_uInt16 GetNum() const override
void InitFill(sal_uInt16 nIndex)
double mfValue
Definition: cellvalue.hxx:40
sal_uInt16 mnFirstXclTab
Name of the last sheet.
Definition: xeformula.hxx:37
ScAddress aEnd
Definition: address.hxx:501
const sal_uInt16 EXC_MAXRECSIZE_BIFF8
Definition: xlstream.hxx:31
DateTime GetDateTime(const css::util::DateTime &_rDT)
#define EXC_CHTR_OP_COLFLAG
Definition: excdefs.hxx:66
#define EXC_STREAM_REVLOG
Definition: excdefs.hxx:63
virtual sal_uInt16 GetNum() const override
ScDocument & GetDoc() const
Returns reference to the destination document (import) or source document (export).
Definition: xlroot.cxx:276
#define EXC_CHTR_NOTHING
Definition: excdefs.hxx:89
RootData & GetOldRoot() const
Returns old RootData struct.
Definition: xlroot.hxx:138
virtual void SaveCont(XclExpStream &rStrm) override
virtual sal_uInt16 GetNum() const override
virtual void SaveActionData(XclExpStream &rStrm) const override
virtual void SaveCont(XclExpStream &rStrm) override
virtual std::size_t GetLen() const override
XclExpXmlChTrHeader(const OUString &rUserName, const DateTime &rDateTime, const sal_uInt8 *pGUID, sal_Int32 nLogNumber, const XclExpChTrTabIdBuffer &rBuf)
ScChangeAction * GetPrev() const
Definition: chgtrack.hxx:324
static bool GetRKFromDouble(sal_Int32 &rnRKValue, double fValue)
Calculates an RK value (encoded integer or double) from a double value.
Definition: xltools.cxx:123
XclExpRefLog maRefLog
XclExpUserBViewList(const ScChangeTrack &rChangeTrack)
static const char * lcl_GetType(XclExpChTrData *pData)
sal_uInt16 GetHour() const
virtual ~XclExpUserBViewList() override
static void Write2DAddress(XclExpStream &rStrm, const ScAddress &rAddress)
void SetGUID(const sal_uInt8 *pGUID)
XclExpChTr0x014A(const XclExpChTrInsert &rAction)
virtual std::size_t GetLen() const override
std::vector< std::unique_ptr< XclExpChTrTabIdBuffer > > maBuffers
Store arbitrary cell value of any kind.
Definition: cellvalue.hxx:36
const XclExpChTrTabIdBuffer & rIdBuffer
virtual ~XclExpChangeTrack() override
#define EXC_CHTR_TYPE_DOUBLE
Definition: excdefs.hxx:83
Access to global data from other classes.
Definition: xeroot.hxx:113
virtual void SaveCont(XclExpStream &rStrm) override
XclExpChTrTabId(sal_uInt16 nCount)
XclExpChTrTabId * pTabId
Definition: root.hxx:62
OUString getNamespaceURL(sal_Int32 nNSID) const
static void lcl_WriteCell(XclExpXmlStream &rStrm, sal_Int32 nElement, const ScAddress &rPosition, XclExpChTrData *pData)
static OString lcl_DateTimeToOString(const DateTime &rDateTime)
sal_uInt32 GetNanoSec() const
virtual sal_uInt16 GetNum() const override
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:43
virtual void Save(XclExpStream &rStrm) override
Writes the record header and calls WriteBody().
ScDocumentUniquePtr xTempDoc
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
std::unique_ptr< XclExpChTrAction > pAddAction
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:314
sal_uInt16 GetMonth() const
Helper to create HLINK records during creation of formatted cell strings.
Definition: xehelper.hxx:175
sal_uInt16 GetBufferCount() const
#define EXC_CHTR_TYPE_RK
Definition: excdefs.hxx:82
XclExpUsersViewBegin(const sal_uInt8 *pGUID, sal_uInt32 nTab)
std::stack< XclExpChTrAction * > aActionStack
sal_uInt16 mnLastXclTab
Calc index of the first sheet.
Definition: xeformula.hxx:38
virtual void SaveXml(XclExpXmlStream &rStrm) override
sal_uInt16 GetMin() const
virtual ~XclExpChTr0x014A() override
virtual void SaveXml(XclExpXmlStream &rStrm) override
std::vector< std::unique_ptr< XclExpChTrAction > > maActions
XclExpChTrInfo(const OUString &rUsername, const DateTime &rDateTime, const sal_uInt8 *pGUID)
void PushStream(sax_fastparser::FSHelperPtr const &aStream)
Definition: xestream.cxx:916
static void lcl_GenerateGUID(sal_uInt8 *pGUID, bool &rValidGUID)
SCTAB Tab() const
Definition: address.hxx:271
void SetRow(SCROW nRowP)
Definition: address.hxx:275
ScAddress aPos
sax_fastparser::FSHelperPtr & GetCurrentStream()
Definition: xestream.cxx:910
static void Write2DRange(XclExpStream &rStrm, const ScRange &rRange)
virtual void CompleteSaveAction(XclExpStream &rStrm) const
virtual sal_uInt16 GetNum() const override
void SetCol(SCCOL nColP)
Definition: address.hxx:279
void PopStream()
Definition: xestream.cxx:921
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2398
virtual std::size_t GetLen() const override
void SetSliceSize(sal_uInt16 nSize)
Sets data slice length.
Definition: xestream.cxx:129
bool GetAccepted() const
virtual void SaveCont(XclExpStream &rStrm) override
const XclExpChTrTabIdBuffer & GetTabIdBuffer() const
virtual ~XclExpChTrAction() override
virtual std::size_t GetLen() const override
const OUString & GetUsername() const
virtual std::size_t GetLen() const override
virtual void SaveActionData(XclExpStream &rStrm) const =0
sal_Int16 GetYear() const
virtual sal_uInt16 GetNum() const override
sal_uInt16 GetSec() const
void WriteXml(XclExpXmlStream &rStrm)
void GetBufferCopy(sal_uInt16 *pDest) const
#define EXC_CHTR_OP_DELROW
Definition: excdefs.hxx:70
XclOutput GetOutput() const
Returns the current output format of the importer/exporter.
Definition: xlroot.hxx:143
OptionalString sType
const SCTAB SC_TAB_APPEND
Definition: address.hxx:84
int i
virtual void SaveActionData(XclExpStream &rStrm) const override
virtual ~XclExpChTr0x0194() override
void IncCol(SCCOL nDelta=1)
Definition: address.hxx:304
void SetAddAction(XclExpChTrAction *pAction)
DateTime maDateTime
XclExpString sUsername
#define EXC_CHTR_OP_CELL
Definition: excdefs.hxx:74
svl::SharedString * mpString
Definition: cellvalue.hxx:41
virtual std::size_t GetLen() const override
virtual void Save(XclExpStream &rStrm) override
Writes the record header and calls WriteBody().
virtual void SaveActionData(XclExpStream &rStrm) const override
static void lcl_WriteUserNamesXml(XclExpXmlStream &rWorkbookStrm)
void Write(XclExpStream &rStrm, const XclExpChTrTabIdBuffer &rTabIdBuffer)
virtual void PrepareSaveAction(XclExpStream &rStrm) const override
virtual sal_uInt16 GetNum() const override
virtual sal_uInt16 GetNum() const override
virtual void SaveCont(XclExpStream &rStrm) override
void IncRow(SCROW nDelta=1)
Definition: address.hxx:300
virtual void SaveXml(XclExpXmlStream &rStrm) override
const XclExpString * mpFirstTab
URL of the document containing the first sheet.
Definition: xeformula.hxx:35
sal_uInt16 GetDay() const
ScBigRange & GetBigRange()
Definition: chgtrack.hxx:232
::std::vector< XclExpRefLogEntry > XclExpRefLog
Vector containing a log for all external references in a formula, used i.e.
Definition: xeformula.hxx:44
XclExpTabInfo & GetTabInfo() const
Returns the buffer for Calc->Excel sheet index conversion.
Definition: xeroot.cxx:75
virtual std::size_t GetActionByteCount() const override
virtual void CompleteSaveAction(XclExpStream &rStrm) const override
virtual void SaveXml(XclExpXmlStream &rStrm) override
virtual std::size_t GetLen() const override
sal_uInt8 aGUID[16]
std::shared_ptr< FastSerializerHelper > FSHelperPtr
ScChangeTrack * CreateTempChangeTrack()
virtual sal_uInt16 GetNum() const override
SC_DLLPUBLIC bool IsEndOfList() const
Definition: chgtrack.cxx:729
XclExpChTrMoveRange(const ScChangeActionMove &rAction, const XclExpRoot &rRoot, const XclExpChTrTabIdBuffer &rTabIdBuffer, const ScChangeTrack &rChangeTrack)
#define EXC_CHTR_OP_DELCOL
Definition: excdefs.hxx:71
virtual sal_uInt16 GetNum() const override
sal_uInt16 GetId(sal_uInt16 nIndex) const
void PushActionRecord(const ScChangeAction &rAction)
SCCOL Col() const
Definition: address.hxx:267
const XclExpRoot & GetRoot() const
Returns this root instance - for code readability in derived classes.
Definition: xeroot.hxx:119
virtual void Save(XclExpStream &rStrm) override
Writes the record header and calls WriteBody().
#define EXC_CHTR_TYPE_FORMULA
Definition: excdefs.hxx:86
XclExpChTrInsertTab(const ScChangeAction &rAction, const XclExpRoot &rRoot, const XclExpChTrTabIdBuffer &rTabIdBuffer)
void SetIndex(sal_uInt32 &rIndex)
void WriteTabId(XclExpStream &rStrm, SCTAB nTabId) const
static OUString GetStreamName(const char *sStreamDir, const char *sStream, sal_Int32 nId)
Definition: xestream.cxx:683
virtual void SaveXml(XclExpXmlStream &rStrm) override
XclExpChTrInsert(const XclExpChTrInsert &rCopy)
virtual void Save(XclExpStream &rStrm) override
Writes the record header and calls WriteBody().
Definition: excrecds.cxx:89
XclExpStringRef mpFormattedString
std::map< sal_uLong, ScChangeAction * > ScChangeActionMap
Definition: chgtrack.hxx:806
XclExpChangeTrack(const XclExpRoot &rRoot)
ScBigAddress aStart
Definition: bigrange.hxx:111
XclExpChTrTabIdBuffer(sal_uInt16 nCount)
sal_Int32 Tab() const
Definition: bigrange.hxx:49
virtual sal_uInt16 GetNum() const override
virtual std::size_t GetLen() const override
sal_uInt16 Len() const
Returns the character count of the string.
Definition: xestring.hxx:114
static void MakeEmptyChTrData(std::unique_ptr< XclExpChTrData > &rpData)
XclExpChTrAction(const XclExpChTrAction &rCopy)
bool isEmpty() const
Definition: cellvalue.cxx:499
#define EXC_CHTR_OP_FORMAT
Definition: excdefs.hxx:75
static XclExpStringRef CreateCellString(const XclExpRoot &rRoot, const OUString &rString, const ScPatternAttr *pCellAttr, XclStrFlags nFlags=XclStrFlags::NONE, sal_uInt16 nMaxLen=EXC_STR_MAXLEN)
Creates a new formatted string from a Calc string cell.
Definition: xehelper.cxx:561
#define EXC_STREAM_USERNAMES
Definition: excdefs.hxx:62
unsigned char sal_uInt8
sal_uInt32 GetActionNumber() const
std::size_t GetSize() const
Returns the byte count the whole string will take on export.
Definition: xestring.cxx:248
virtual void SaveXml(XclExpXmlStream &rStrm) override
std::vector< XclExpUserBView > aViews
sal_uInt8 aGUID[16]
XclExpUserBView(const OUString &rUsername, const sal_uInt8 *pGUID)
sax_fastparser::FSHelperPtr CreateOutputStream(const OUString &sFullStream, const OUString &sRelativeStream, const css::uno::Reference< css::io::XOutputStream > &xParentRelation, const char *sContentType, std::u16string_view sRelationshipType, OUString *pRelationshipId=nullptr)
Definition: xestream.cxx:939
std::vector< sal_uInt16 > maTabBuffer
#define EXC_CHTR_OP_UNKNOWN
Definition: excdefs.hxx:76
const ScAddress & GetXclMaxPos() const
Returns the highest possible cell address in an Excel document (using current BIFF version)...
Definition: xlroot.hxx:245
#define EXC_CHTR_TYPE_STRING
Definition: excdefs.hxx:84
virtual std::size_t GetLen() const override
virtual void SaveCont(XclExpStream &rStrm) override
static const char * lcl_GetAction(sal_uInt16 nOpCode)
const XclExpString * mpUrl
Definition: xeformula.hxx:34
XclTokenArrayRef CreateFormula(XclFormulaType eType, const ScTokenArray &rScTokArr, const ScAddress *pScBasePos=nullptr, XclExpRefLog *pRefLog=nullptr)
Creates and returns the token array of a formula.
Definition: xeformula.cxx:2637
#define EXC_CHTR_OP_INSCOL
Definition: excdefs.hxx:69
XclExpString sUsername
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:401
#define EXC_CHTR_OP_INSROW
Definition: excdefs.hxx:68
virtual void SaveCont(XclExpStream &rStrm) override
void SetNanoSec(sal_uInt32 nNewNanoSec)
virtual ~XclExpChTrCellContent() override
Log entry for external references in a formula, used i.e.
Definition: xeformula.hxx:32
EditTextObject * mpEditText
Definition: cellvalue.hxx:42
bool ForceInfoRecord() const
constexpr sal_Int32 FSNS(sal_Int32 namespc, sal_Int32 element)
static std::size_t GetHeaderByteCount()
virtual std::size_t GetActionByteCount() const =0
virtual void SaveCont(XclExpStream &rStrm) override
#define EXC_CHTR_OP_MOVE
Definition: excdefs.hxx:72
const ScFormulaCell * mpFormulaCell
std::unique_ptr< XclExpChTrData > pNewData
const std::set< OUString > & GetUserCollection() const
Definition: chgtrack.hxx:979
static SC_DLLPUBLIC OUString GetString(const EditTextObject &rEditText, const ScDocument *pDoc)
Retrieves string with paragraphs delimited by new lines (' ').
Definition: editutil.cxx:115
std::unique_ptr< XclExpString > pString
void EnableEncryption(bool bEnable=true)
Definition: xestream.cxx:358
virtual sal_uInt16 GetNum() const override
XclTokenArrayRef mxTokArr
sal_Int32 nLength
static void lcl_WriteFixedString(XclExpStream &rStrm, const XclExpString &rString, std::size_t nLength)
SC_DLLPUBLIC ScChangeTrack * Clone(ScDocument *pDocument) const
Definition: chgtrack.cxx:4405
const ScCellValue & GetNewCell() const
Definition: chgtrack.hxx:747
virtual ~XclExpChTr0x0195() override
#define EXC_CHTR_ACCEPT
Definition: excdefs.hxx:90
tools::SvRef< SotStorageStream > OpenStream(tools::SvRef< SotStorage > const &xStrg, const OUString &rStrmName) const
Tries to open a new stream in the specified storage for reading or writing.
Definition: xlroot.cxx:264
SC_DLLPUBLIC void GetDependents(ScChangeAction *, ScChangeActionMap &, bool bListMasterDelete=false, bool bAllFlat=false) const
Definition: chgtrack.cxx:3846
void SetCount(sal_uInt32 nNew)
SC_DLLPUBLIC void GetDelta(sal_Int32 &nDx, sal_Int32 &nDy, sal_Int32 &nDz) const
Definition: chgtrack.cxx:1167
virtual sal_uInt16 GetNum() const override
virtual sal_uInt16 GetNum() const override
virtual ~XclExpChTrInfo() override
virtual std::size_t GetLen() const override
void Copy(const XclExpChTrTabIdBuffer &rBuffer)
virtual std::size_t GetLen() const override
virtual ~XclExpChTrMoveRange() override
static void lcl_WriteDateTime(XclExpStream &rStrm, const DateTime &rDateTime)
virtual ~XclExpChTrInsertTab() override
OUString maUserName
sc::CompileFormulaContext & GetCompileFormulaContext() const
Definition: xeroot.hxx:122
virtual void PrepareSaveAction(XclExpStream &rStrm) const
std::size_t GetBufferSize() const
Returns the byte count the character buffer will take on export.
Definition: xestring.cxx:243
virtual std::size_t GetActionByteCount() const override
static OString lcl_GuidToOString(sal_uInt8 aGuid[16])
const DateTime & GetDateTime() const
virtual void PrepareSaveAction(XclExpStream &rStrm) const override
sal_Int16 SCTAB
Definition: types.hxx:23
void WriteZeroBytes(std::size_t nBytes)
Writes a sequence of nBytes zero bytes (respects slice setting).
Definition: xestream.cxx:256
virtual sal_uInt16 GetNum() const override
virtual void SaveXml(XclExpXmlStream &rStrm) override