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";
972  {
973  ScFormulaCell* pFormulaCell = const_cast< ScFormulaCell* >( pData->mpFormulaCell );
974  const char* sType;
975  OUString sValue;
976  XclXmlUtils::GetFormulaTypeAndValue( *pFormulaCell, sType, sValue );
977  return sType;
978  }
979  break;
981  return "inlineStr";
982  break;
983  default:
984  break;
985  }
986  return "*unknown*";
987 }
988 
989 static void lcl_WriteCell( XclExpXmlStream& rStrm, sal_Int32 nElement, const ScAddress& rPosition, XclExpChTrData* pData )
990 {
992 
993  pStream->startElement(nElement,
994  XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), rPosition),
995  XML_s, nullptr, // OOXTODO: not supported
996  XML_t, lcl_GetType(pData),
997  XML_cm, nullptr, // OOXTODO: not supported
998  XML_vm, nullptr, // OOXTODO: not supported
999  XML_ph, nullptr); // OOXTODO: not supported
1000  switch( pData->nType )
1001  {
1002  case EXC_CHTR_TYPE_RK:
1003  case EXC_CHTR_TYPE_DOUBLE:
1004  pStream->startElement(XML_v);
1005  pStream->write( pData->fValue );
1006  pStream->endElement( XML_v );
1007  break;
1008  case EXC_CHTR_TYPE_FORMULA:
1009  pStream->startElement( XML_f
1010  // OOXTODO: other attributes? see XclExpFormulaCell::SaveXml()
1011  );
1012  pStream->writeEscaped( XclXmlUtils::ToOUString(
1014  pData->mpFormulaCell->aPos, pData->mpFormulaCell->GetCode()));
1015  pStream->endElement( XML_f );
1016  break;
1017  case EXC_CHTR_TYPE_STRING:
1018  pStream->startElement(XML_is);
1019  if( pData->mpFormattedString )
1020  pData->mpFormattedString->WriteXml( rStrm );
1021  else
1022  pData->pString->WriteXml( rStrm );
1023  pStream->endElement( XML_is );
1024  break;
1025  default:
1026  // ignore
1027  break;
1028  }
1029  pStream->endElement( nElement );
1030 }
1031 
1033 {
1034  sax_fastparser::FSHelperPtr pStream = rRevisionLogStrm.GetCurrentStream();
1035  pStream->startElement( XML_rcc,
1036  XML_rId, OString::number(GetActionNumber()),
1037  XML_ua, ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1038  XML_ra, nullptr, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1039  XML_sId, OString::number(GetTabId(aPosition.Tab())),
1040  XML_odxf, nullptr, // OOXTODO: not supported
1041  XML_xfDxf, nullptr, // OOXTODO: not supported
1042  XML_s, nullptr, // OOXTODO: not supported
1043  XML_dxf, nullptr, // OOXTODO: not supported
1044  XML_numFmtId, nullptr, // OOXTODO: not supported
1045  XML_quotePrefix, nullptr, // OOXTODO: not supported
1046  XML_oldQuotePrefix, nullptr, // OOXTODO: not supported
1047  XML_ph, nullptr, // OOXTODO: not supported
1048  XML_oldPh, nullptr, // OOXTODO: not supported
1049  XML_endOfListFormulaUpdate, nullptr); // OOXTODO: not supported
1050  if( pOldData )
1051  {
1052  lcl_WriteCell( rRevisionLogStrm, XML_oc, aPosition, pOldData.get() );
1053  if (!pNewData)
1054  {
1055  pStream->singleElement(XML_nc, XML_r, XclXmlUtils::ToOString(rRevisionLogStrm.GetRoot().GetDoc(), aPosition));
1056  }
1057  }
1058  if( pNewData )
1059  {
1060  lcl_WriteCell( rRevisionLogStrm, XML_nc, aPosition, pNewData.get() );
1061  }
1062  // OOXTODO: XML_odxf, XML_ndxf, XML_extLst elements
1063  pStream->endElement( XML_rcc );
1064 }
1065 
1067  XclExpChTrAction(rCopy),
1068  mbEndOfList(rCopy.mbEndOfList),
1069  aRange(rCopy.aRange) {}
1070 
1072  const ScChangeAction& rAction,
1073  const XclExpRoot& rRoot,
1074  const XclExpChTrTabIdBuffer& rTabIdBuffer,
1075  const ScChangeTrack& rChangeTrack ) :
1076  XclExpChTrAction( rAction, rRoot, rTabIdBuffer ),
1077  mbEndOfList(false),
1078  aRange( rAction.GetBigRange().MakeRange() )
1079 {
1080  nLength = 0x00000030;
1081  switch( rAction.GetType() )
1082  {
1084  case SC_CAT_INSERT_ROWS:
1085  {
1086  const ScChangeActionIns& rIns = static_cast<const ScChangeActionIns&>(rAction);
1087  mbEndOfList = rIns.IsEndOfList();
1089  }
1090  break;
1093  default:
1094  OSL_FAIL( "XclExpChTrInsert::XclExpChTrInsert - unknown action" );
1095  }
1096 
1098  {
1099  aRange.aStart.SetRow( 0 );
1100  aRange.aEnd.SetRow( rRoot.GetXclMaxPos().Row() );
1101  }
1102  else
1103  {
1104  aRange.aStart.SetCol( 0 );
1105  aRange.aEnd.SetCol( rRoot.GetXclMaxPos().Col() );
1106  }
1107 
1109  {
1110  SetAddAction( new XclExpChTr0x014A( *this ) );
1111  AddDependentContents( rAction, rRoot, rChangeTrack );
1112  }
1113 }
1114 
1116 {
1117 }
1118 
1120 {
1121  WriteTabId( rStrm, aRange.aStart.Tab() );
1122  sal_uInt16 nFlagVal = mbEndOfList ? 0x0001 : 0x0000;
1123  rStrm << nFlagVal;
1124  Write2DRange( rStrm, aRange );
1125  rStrm << sal_uInt32(0x00000000);
1126 }
1127 
1129 {
1131  XclExpChTrEmpty( 0x0150 ).Save( rStrm );
1132 }
1133 
1135 {
1137  XclExpChTrEmpty( 0x0151 ).Save( rStrm );
1138 }
1139 
1140 sal_uInt16 XclExpChTrInsert::GetNum() const
1141 {
1142  return 0x0137;
1143 }
1144 
1146 {
1147  return 16;
1148 }
1149 
1150 static const char* lcl_GetAction( sal_uInt16 nOpCode )
1151 {
1152  switch( nOpCode )
1153  {
1154  case EXC_CHTR_OP_INSCOL: return "insertCol";
1155  case EXC_CHTR_OP_INSROW: return "insertRow";
1156  case EXC_CHTR_OP_DELCOL: return "deleteCol";
1157  case EXC_CHTR_OP_DELROW: return "deleteRow";
1158  default: return "*unknown*";
1159  }
1160 }
1161 
1163 {
1164  sax_fastparser::FSHelperPtr pStream = rRevisionLogStrm.GetCurrentStream();
1165  pStream->startElement( XML_rrc,
1166  XML_rId, OString::number(GetActionNumber()),
1167  XML_ua, ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1168  XML_ra, nullptr, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1169  XML_sId, OString::number(GetTabId(aRange.aStart.Tab())),
1170  XML_eol, ToPsz10(mbEndOfList),
1171  XML_ref, XclXmlUtils::ToOString(rRevisionLogStrm.GetRoot().GetDoc(), aRange),
1172  XML_action, lcl_GetAction( nOpCode ),
1173  XML_edge, nullptr); // OOXTODO: ???
1174 
1175  // OOXTODO: does this handle XML_rfmt, XML_undo?
1176  XclExpChTrAction* pAction = GetAddAction();
1177  while( pAction != nullptr )
1178  {
1179  pAction->SaveXml( rRevisionLogStrm );
1180  pAction = pAction->GetAddAction();
1181  }
1182  pStream->endElement( XML_rrc );
1183 }
1184 
1186  const ScChangeAction& rAction,
1187  const XclExpRoot& rRoot,
1188  const XclExpChTrTabIdBuffer& rTabIdBuffer ) :
1189  XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_INSTAB ),
1190  XclExpRoot( rRoot ),
1191  nTab( static_cast<SCTAB>(rAction.GetBigRange().aStart.Tab()) )
1192 {
1193  nLength = 0x0000021C;
1194  bForceInfo = true;
1195 }
1196 
1198 {
1199 }
1200 
1202 {
1203  WriteTabId( rStrm, nTab );
1204  rStrm << sal_uInt32( 0 );
1205  lcl_WriteFixedString( rStrm, XclExpString( GetTabInfo().GetScTabName( nTab ) ), 127 );
1206  lcl_WriteDateTime( rStrm, GetDateTime() );
1207  rStrm.WriteZeroBytes( 133 );
1208 }
1209 
1211 {
1212  return 0x014D;
1213 }
1214 
1216 {
1217  return 276;
1218 }
1219 
1221 {
1223  pStream->singleElement( XML_ris,
1224  XML_rId, OString::number(GetActionNumber()),
1225  XML_ua, ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1226  XML_ra, nullptr, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1227  XML_sheetId, OString::number(GetTabId(nTab)),
1228  XML_name, GetTabInfo().GetScTabName(nTab).toUtf8(),
1229  XML_sheetPosition, OString::number(nTab) );
1230 }
1231 
1233  const ScChangeActionMove& rAction,
1234  const XclExpRoot& rRoot,
1235  const XclExpChTrTabIdBuffer& rTabIdBuffer,
1236  const ScChangeTrack& rChangeTrack ) :
1237  XclExpChTrAction( rAction, rRoot, rTabIdBuffer, EXC_CHTR_OP_MOVE ),
1238  aDestRange( rAction.GetBigRange().MakeRange() )
1239 {
1240  nLength = 0x00000042;
1242  sal_Int32 nDCols, nDRows, nDTabs;
1243  rAction.GetDelta( nDCols, nDRows, nDTabs );
1244  aSourceRange.aStart.IncRow( static_cast<SCROW>(-nDRows) );
1245  aSourceRange.aStart.IncCol( static_cast<SCCOL>(-nDCols) );
1246  aSourceRange.aStart.IncTab( static_cast<SCTAB>(-nDTabs) );
1247  aSourceRange.aEnd.IncRow( static_cast<SCROW>(-nDRows) );
1248  aSourceRange.aEnd.IncCol( static_cast<SCCOL>(-nDCols) );
1249  aSourceRange.aEnd.IncTab( static_cast<SCTAB>(-nDTabs) );
1250  AddDependentContents( rAction, rRoot, rChangeTrack );
1251 }
1252 
1254 {
1255 }
1256 
1258 {
1259  WriteTabId( rStrm, aDestRange.aStart.Tab() );
1260  Write2DRange( rStrm, aSourceRange );
1261  Write2DRange( rStrm, aDestRange );
1262  WriteTabId( rStrm, aSourceRange.aStart.Tab() );
1263  rStrm << sal_uInt32(0x00000000);
1264 }
1265 
1267 {
1268  XclExpChTrEmpty( 0x014E ).Save( rStrm );
1269 }
1270 
1272 {
1273  XclExpChTrEmpty( 0x014F ).Save( rStrm );
1274 }
1275 
1277 {
1278  return 0x0140;
1279 }
1280 
1282 {
1283  return 24;
1284 }
1285 
1287 {
1288  sax_fastparser::FSHelperPtr pStream = rRevisionLogStrm.GetCurrentStream();
1289 
1290  pStream->startElement( XML_rm,
1291  XML_rId, OString::number(GetActionNumber()),
1292  XML_ua, ToPsz( GetAccepted () ), // OOXTODO? bAccepted == ua or ra; not sure.
1293  XML_ra, nullptr, // OOXTODO: RRD.fUndoAction? Or RRD.fAccepted?
1294  XML_sheetId, OString::number(GetTabId(aDestRange.aStart.Tab())),
1295  XML_source, XclXmlUtils::ToOString(rRevisionLogStrm.GetRoot().GetDoc(), aSourceRange),
1296  XML_destination, XclXmlUtils::ToOString(rRevisionLogStrm.GetRoot().GetDoc(), aDestRange),
1297  XML_sourceSheetId, OString::number(GetTabId(aSourceRange.aStart.Tab())) );
1298  // OOXTODO: does this handle XML_rfmt, XML_undo?
1299  XclExpChTrAction* pAction = GetAddAction();
1300  while( pAction != nullptr )
1301  {
1302  pAction->SaveXml( rRevisionLogStrm );
1303  pAction = pAction->GetAddAction();
1304  }
1305  pStream->endElement( XML_rm );
1306 }
1307 
1309  XclExpChTrInsert( rAction )
1310 {
1311  nLength = 0x00000026;
1313 }
1314 
1316 {
1317 }
1318 
1320 {
1321  WriteTabId( rStrm, aRange.aStart.Tab() );
1322  rStrm << sal_uInt16(0x0003)
1323  << sal_uInt16(0x0001);
1324  Write2DRange( rStrm, aRange );
1325 }
1326 
1327 sal_uInt16 XclExpChTr0x014A::GetNum() const
1328 {
1329  return 0x014A;
1330 }
1331 
1333 {
1334  return 14;
1335 }
1336 
1338 {
1340 
1341  pStream->startElement( XML_rfmt,
1342  XML_sheetId, OString::number(GetTabId(aRange.aStart.Tab())),
1343  XML_xfDxf, nullptr, // OOXTODO: not supported
1344  XML_s, nullptr, // OOXTODO: style
1345  XML_sqref, XclXmlUtils::ToOString(rStrm.GetRoot().GetDoc(), aRange),
1346  XML_start, nullptr, // OOXTODO: for string changes
1347  XML_length, nullptr); // OOXTODO: for string changes
1348  // OOXTODO: XML_dxf, XML_extLst
1349 
1350  pStream->endElement( XML_rfmt );
1351 }
1352 
1353 std::size_t ExcXmlRecord::GetLen() const
1354 {
1355  return 0;
1356 }
1357 
1358 sal_uInt16 ExcXmlRecord::GetNum() const
1359 {
1360  return 0;
1361 }
1362 
1364 {
1365  // Do nothing; ignored for BIFF output.
1366 }
1367 
1368 namespace {
1369 
1370 class EndXmlElement : public ExcXmlRecord
1371 {
1372  sal_Int32 mnElement;
1373 public:
1374  explicit EndXmlElement( sal_Int32 nElement ) : mnElement( nElement) {}
1375  virtual void SaveXml( XclExpXmlStream& rStrm ) override;
1376 };
1377 
1378 }
1379 
1380 void EndXmlElement::SaveXml( XclExpXmlStream& rStrm )
1381 {
1383  pStream->write("</")->writeId(mnElement)->write(">");
1384 }
1385 
1387  XclExpRoot( rRoot ),
1388  aActionStack(),
1389  pTabIdBuffer( nullptr )
1390 {
1391  OSL_ENSURE( GetOldRoot().pTabId, "XclExpChangeTrack::XclExpChangeTrack - root data incomplete" );
1392  if( !GetOldRoot().pTabId )
1393  return;
1394 
1395  ScChangeTrack* pTempChangeTrack = CreateTempChangeTrack();
1396  if (!pTempChangeTrack)
1397  return;
1398 
1399  pTabIdBuffer = new XclExpChTrTabIdBuffer( GetTabInfo().GetXclTabCount() );
1400  maBuffers.push_back( std::unique_ptr<XclExpChTrTabIdBuffer>(pTabIdBuffer) );
1401 
1402  // calculate final table order (tab id list)
1403  const ScChangeAction* pScAction;
1404  for( pScAction = pTempChangeTrack->GetLast(); pScAction; pScAction = pScAction->GetPrev() )
1405  {
1406  if( pScAction->GetType() == SC_CAT_INSERT_TABS )
1407  {
1408  SCTAB nScTab = static_cast< SCTAB >( pScAction->GetBigRange().aStart.Tab() );
1409  pTabIdBuffer->InitFill( GetTabInfo().GetXclTab( nScTab ) );
1410  }
1411  }
1414 
1415  // get actions in reverse order
1416  pScAction = pTempChangeTrack->GetLast();
1417  while( pScAction )
1418  {
1419  PushActionRecord( *pScAction );
1420  const ScChangeAction* pPrevAction = pScAction->GetPrev();
1421  pScAction = pPrevAction;
1422  }
1423 
1424  // build record list
1425  if (GetOutput() == EXC_OUTPUT_BINARY)
1426  {
1427  XclExpChTrHeader* pHeader = new XclExpChTrHeader; // header record for last GUID
1428  maRecList.push_back( std::unique_ptr<ExcRecord>(pHeader) );
1429  maRecList.push_back( std::unique_ptr<ExcRecord>( new XclExpChTr0x0195 ) );
1430  maRecList.push_back( std::unique_ptr<ExcRecord>( new XclExpChTr0x0194( *pTempChangeTrack ) ) );
1431 
1432  OUString sLastUsername;
1433  DateTime aLastDateTime( DateTime::EMPTY );
1434  sal_uInt32 nIndex = 1;
1435  sal_Int32 nLogNumber = 1;
1436  sal_uInt8 aGUID[ 16 ]; // GUID for action info records
1437  bool bValidGUID = false;
1438  while( !aActionStack.empty() )
1439  {
1440  XclExpChTrAction* pAction = aActionStack.top();
1441  aActionStack.pop();
1442 
1443  if( (nIndex == 1) || pAction->ForceInfoRecord() ||
1444  (pAction->GetUsername() != sLastUsername) ||
1445  (pAction->GetDateTime() != aLastDateTime) )
1446  {
1447  lcl_GenerateGUID( aGUID, bValidGUID );
1448  sLastUsername = pAction->GetUsername();
1449  aLastDateTime = pAction->GetDateTime();
1450 
1451  nLogNumber++;
1452  maRecList.push_back( std::unique_ptr<ExcRecord>(new XclExpChTrInfo(sLastUsername, aLastDateTime, aGUID)) );
1453  maRecList.push_back( std::unique_ptr<ExcRecord>(new XclExpChTrTabId(pAction->GetTabIdBuffer())) );
1454  pHeader->SetGUID( aGUID );
1455  }
1456  pAction->SetIndex( nIndex );
1457  maRecList.push_back( std::unique_ptr<ExcRecord>(pAction) );
1458  }
1459 
1460  pHeader->SetGUID( aGUID );
1461  pHeader->SetCount( nIndex - 1 );
1462  maRecList.push_back( std::unique_ptr<ExcRecord>(new ExcEof) );
1463  }
1464  else
1465  {
1467  maRecList.push_back( std::unique_ptr<ExcRecord>(pHeaders));
1468 
1469  OUString sLastUsername;
1470  DateTime aLastDateTime(DateTime::EMPTY);
1471  sal_uInt32 nIndex = 1;
1472  sal_Int32 nLogNumber = 1;
1473  XclExpXmlChTrHeader* pCurHeader = nullptr;
1474  sal_uInt8 aGUID[ 16 ]; // GUID for action info records
1475  bool bValidGUID = false;
1476 
1477  while (!aActionStack.empty())
1478  {
1479  XclExpChTrAction* pAction = aActionStack.top();
1480  aActionStack.pop();
1481 
1482  if( (nIndex == 1) || pAction->ForceInfoRecord() ||
1483  (pAction->GetUsername() != sLastUsername) ||
1484  (pAction->GetDateTime() != aLastDateTime) )
1485  {
1486  lcl_GenerateGUID( aGUID, bValidGUID );
1487  sLastUsername = pAction->GetUsername();
1488  aLastDateTime = pAction->GetDateTime();
1489 
1490  pCurHeader = new XclExpXmlChTrHeader(sLastUsername, aLastDateTime, aGUID, nLogNumber, pAction->GetTabIdBuffer());
1491  maRecList.push_back( std::unique_ptr<ExcRecord>(pCurHeader));
1492  nLogNumber++;
1493  pHeaders->SetGUID(aGUID);
1494  }
1495  pAction->SetIndex(nIndex);
1496  pCurHeader->AppendAction(std::unique_ptr<XclExpChTrAction>(pAction));
1497  }
1498 
1499  pHeaders->SetGUID(aGUID);
1500  maRecList.push_back( std::unique_ptr<ExcRecord>(new EndXmlElement(XML_headers)));
1501  }
1502 }
1503 
1505 {
1506  while( !aActionStack.empty() )
1507  {
1508  delete aActionStack.top();
1509  aActionStack.pop();
1510  }
1511 }
1512 
1514 {
1515  // get original change track
1516  ScChangeTrack* pOrigChangeTrack = GetDoc().GetChangeTrack();
1517  OSL_ENSURE( pOrigChangeTrack, "XclExpChangeTrack::CreateTempChangeTrack - no change track data" );
1518  if( !pOrigChangeTrack )
1519  return nullptr;
1520 
1521  assert(!xTempDoc);
1522  // create empty document
1523  xTempDoc.reset(new ScDocument);
1524 
1525  // adjust table count
1526  SCTAB nOrigCount = GetDoc().GetTableCount();
1527  OUString sTabName;
1528  for( sal_Int32 nIndex = 0; nIndex < nOrigCount; nIndex++ )
1529  {
1530  xTempDoc->CreateValidTabName(sTabName);
1531  xTempDoc->InsertTab(SC_TAB_APPEND, sTabName);
1532  }
1533  OSL_ENSURE(nOrigCount == xTempDoc->GetTableCount(),
1534  "XclExpChangeTrack::CreateTempChangeTrack - table count mismatch");
1535  if(nOrigCount != xTempDoc->GetTableCount())
1536  return nullptr;
1537 
1538  return pOrigChangeTrack->Clone(xTempDoc.get());
1539 }
1540 
1542 {
1543  XclExpChTrAction* pXclAction = nullptr;
1544  ScChangeTrack* pTempChangeTrack = xTempDoc->GetChangeTrack();
1545  switch( rAction.GetType() )
1546  {
1547  case SC_CAT_CONTENT:
1548  pXclAction = new XclExpChTrCellContent( static_cast<const ScChangeActionContent&>(rAction), GetRoot(), *pTabIdBuffer );
1549  break;
1550  case SC_CAT_INSERT_ROWS:
1551  case SC_CAT_INSERT_COLS:
1552  case SC_CAT_DELETE_ROWS:
1553  case SC_CAT_DELETE_COLS:
1554  if (pTempChangeTrack)
1555  pXclAction = new XclExpChTrInsert( rAction, GetRoot(), *pTabIdBuffer, *pTempChangeTrack );
1556  break;
1557  case SC_CAT_INSERT_TABS:
1558  {
1559  pXclAction = new XclExpChTrInsertTab( rAction, GetRoot(), *pTabIdBuffer );
1561  pNewBuffer->Remove();
1562  maBuffers.push_back( std::unique_ptr<XclExpChTrTabIdBuffer>(pNewBuffer) );
1563  pTabIdBuffer = pNewBuffer;
1564  }
1565  break;
1566  case SC_CAT_MOVE:
1567  if (pTempChangeTrack)
1568  pXclAction = new XclExpChTrMoveRange( static_cast<const ScChangeActionMove&>(rAction), GetRoot(), *pTabIdBuffer, *pTempChangeTrack );
1569  break;
1570  default:;
1571  }
1572  if( pXclAction )
1573  aActionStack.push( pXclAction );
1574 }
1575 
1577 {
1578  bool bRet = false;
1580  OSL_ENSURE( xSvStrm.is(), "XclExpChangeTrack::WriteUserNamesStream - no stream" );
1581  if( xSvStrm.is() )
1582  {
1583  XclExpStream aXclStrm( *xSvStrm, GetRoot() );
1584  XclExpChTr0x0191().Save( aXclStrm );
1585  XclExpChTr0x0198().Save( aXclStrm );
1586  XclExpChTr0x0192().Save( aXclStrm );
1587  XclExpChTr0x0197().Save( aXclStrm );
1588  xSvStrm->Commit();
1589  bRet = true;
1590  }
1591  return bRet;
1592 }
1593 
1595 {
1596  if (maRecList.empty())
1597  return;
1598 
1599  if( !WriteUserNamesStream() )
1600  return;
1601 
1603  OSL_ENSURE( xSvStrm.is(), "XclExpChangeTrack::Write - no stream" );
1604  if( xSvStrm.is() )
1605  {
1606  XclExpStream aXclStrm( *xSvStrm, GetRoot(), EXC_MAXRECSIZE_BIFF8 + 8 );
1607 
1608  for(const auto& rxRec : maRecList)
1609  rxRec->Save(aXclStrm);
1610 
1611  xSvStrm->Commit();
1612  }
1613 }
1614 
1615 static void lcl_WriteUserNamesXml( XclExpXmlStream& rWorkbookStrm )
1616 {
1617  sax_fastparser::FSHelperPtr pUserNames = rWorkbookStrm.CreateOutputStream(
1618  "xl/revisions/userNames.xml",
1619  u"revisions/userNames.xml",
1620  rWorkbookStrm.GetCurrentStream()->getOutputStream(),
1621  "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml",
1622  CREATE_OFFICEDOC_RELATION_TYPE("usernames"));
1623  pUserNames->startElement( XML_users,
1624  XML_xmlns, rWorkbookStrm.getNamespaceURL(OOX_NS(xls)).toUtf8(),
1625  FSNS( XML_xmlns, XML_r ), rWorkbookStrm.getNamespaceURL(OOX_NS(officeRel)).toUtf8(),
1626  XML_count, "0" );
1627  // OOXTODO: XML_userinfo elements for each user editing the file
1628  // Doesn't seem to be supported by .xls output either (based on
1629  // contents of XclExpChangeTrack::WriteUserNamesStream()).
1630  pUserNames->endElement( XML_users );
1631 }
1632 
1634 {
1635  if (maRecList.empty())
1636  return;
1637 
1638  lcl_WriteUserNamesXml( rWorkbookStrm );
1639 
1640  sax_fastparser::FSHelperPtr pRevisionHeaders = rWorkbookStrm.CreateOutputStream(
1641  "xl/revisions/revisionHeaders.xml",
1642  u"revisions/revisionHeaders.xml",
1643  rWorkbookStrm.GetCurrentStream()->getOutputStream(),
1644  "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml",
1645  CREATE_OFFICEDOC_RELATION_TYPE("revisionHeaders"));
1646  // OOXTODO: XML_userinfo elements for each user editing the file
1647  // Doesn't seem to be supported by .xls output either (based on
1648  // contents of XclExpChangeTrack::WriteUserNamesStream()).
1649  rWorkbookStrm.PushStream( pRevisionHeaders );
1650 
1651  for (const auto& rxRec : maRecList)
1652  rxRec->SaveXml(rWorkbookStrm);
1653 
1654  rWorkbookStrm.PopStream();
1655 }
1656 
1657 /* 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:300
virtual std::size_t GetActionByteCount() const override
bool is() const
This class stores an unformatted or formatted string for Excel export.
Definition: xestring.hxx:47
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:216
static void GetFormulaTypeAndValue(ScFormulaCell &rCell, const char *&sType, OUString &rValue)
Definition: xestream.cxx:658
virtual void SaveActionData(XclExpStream &rStrm) const override
static OString ToOString(const Color &rColor)
Definition: xestream.cxx:699
const ScCellValue & GetOldCell() const
Definition: chgtrack.hxx:745
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:37
OUString getString() const
ScAddress aStart
Definition: address.hxx:499
virtual sal_uInt16 GetNum() const override
virtual void SaveCont(XclExpStream &rStrm) override
virtual sal_uInt16 GetNum() const override
ScChangeActionType GetType() const
Definition: chgtrack.hxx:317
std::unique_ptr< sal_uInt16[]> pBuffer
virtual std::size_t GetLen() const override
virtual ~XclExpChTrEmpty() override
#define EMPTY_OUSTRING
Definition: global.hxx:213
#define EXC_CHTR_TYPE_EMPTY
Definition: excdefs.hxx:80
const XclExpRoot & GetRoot() const
Returns the filter root data.
Definition: xestream.hxx:291
virtual void SaveXml(XclExpXmlStream &rStrm) override
void IncTab(SCTAB nDelta=1)
Definition: address.hxx:307
This class is used to export Excel record streams.
Definition: xestream.hxx:72
SCROW Row() const
Definition: address.hxx:261
virtual void SaveCont(XclExpStream &rStrm) override
#define EXC_CHTR_OP_DELFLAG
Definition: excdefs.hxx:66
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:959
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:784
ScTokenArray * GetCode()
virtual ~XclExpChTrHeader() override
virtual void CompleteSaveAction(XclExpStream &rStrm) const override
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: excrecds.cxx:105
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:72
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:39
sal_uInt16 mnFirstXclTab
Name of the last sheet.
Definition: xeformula.hxx:36
ScAddress aEnd
Definition: address.hxx:500
const sal_uInt16 EXC_MAXRECSIZE_BIFF8
Definition: xlstream.hxx:30
DateTime GetDateTime(const css::util::DateTime &_rDT)
#define EXC_CHTR_OP_COLFLAG
Definition: excdefs.hxx:65
#define EXC_STREAM_REVLOG
Definition: excdefs.hxx:62
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:88
RootData & GetOldRoot() const
Returns old RootData struct.
Definition: xlroot.hxx:137
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:323
static bool GetRKFromDouble(sal_Int32 &rnRKValue, double fValue)
Calculates an RK value (encoded integer or double) from a double value.
Definition: xltools.cxx:124
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:35
const XclExpChTrTabIdBuffer & rIdBuffer
virtual ~XclExpChangeTrack() override
#define EXC_CHTR_TYPE_DOUBLE
Definition: excdefs.hxx:82
Access to global data from other classes.
Definition: xeroot.hxx:112
virtual void SaveCont(XclExpStream &rStrm) override
XclExpChTrTabId(sal_uInt16 nCount)
XclExpChTrTabId * pTabId
Definition: root.hxx:60
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:42
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:313
sal_uInt16 GetMonth() const
Helper to create HLINK records during creation of formatted cell strings.
Definition: xehelper.hxx:177
sal_uInt16 GetBufferCount() const
#define EXC_CHTR_TYPE_RK
Definition: excdefs.hxx:81
XclExpUsersViewBegin(const sal_uInt8 *pGUID, sal_uInt32 nTab)
std::stack< XclExpChTrAction * > aActionStack
sal_uInt16 mnLastXclTab
Calc index of the first sheet.
Definition: xeformula.hxx:37
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:917
static void lcl_GenerateGUID(sal_uInt8 *pGUID, bool &rValidGUID)
SCTAB Tab() const
Definition: address.hxx:270
void SetRow(SCROW nRowP)
Definition: address.hxx:274
ScAddress aPos
sax_fastparser::FSHelperPtr & GetCurrentStream()
Definition: xestream.cxx:911
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:278
void PopStream()
Definition: xestream.cxx:922
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2399
virtual std::size_t GetLen() const override
void SetSliceSize(sal_uInt16 nSize)
Sets data slice length.
Definition: xestream.cxx:130
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:69
XclOutput GetOutput() const
Returns the current output format of the importer/exporter.
Definition: xlroot.hxx:142
OptionalString sType
const SCTAB SC_TAB_APPEND
Definition: address.hxx:83
int i
virtual void SaveActionData(XclExpStream &rStrm) const override
virtual ~XclExpChTr0x0194() override
void IncCol(SCCOL nDelta=1)
Definition: address.hxx:303
void SetAddAction(XclExpChTrAction *pAction)
DateTime maDateTime
sax_fastparser::FSHelperPtr CreateOutputStream(const OUString &sFullStream, std::u16string_view sRelativeStream, const css::uno::Reference< css::io::XOutputStream > &xParentRelation, const char *sContentType, std::u16string_view sRelationshipType, OUString *pRelationshipId=nullptr)
Definition: xestream.cxx:940
XclExpString sUsername
#define EXC_CHTR_OP_CELL
Definition: excdefs.hxx:73
svl::SharedString * mpString
Definition: cellvalue.hxx:40
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:299
virtual void SaveXml(XclExpXmlStream &rStrm) override
const XclExpString * mpFirstTab
URL of the document containing the first sheet.
Definition: xeformula.hxx:34
float u
sal_uInt16 GetDay() const
ScBigRange & GetBigRange()
Definition: chgtrack.hxx:231
::std::vector< XclExpRefLogEntry > XclExpRefLog
Vector containing a log for all external references in a formula, used i.e.
Definition: xeformula.hxx:43
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:702
XclExpChTrMoveRange(const ScChangeActionMove &rAction, const XclExpRoot &rRoot, const XclExpChTrTabIdBuffer &rTabIdBuffer, const ScChangeTrack &rChangeTrack)
#define EXC_CHTR_OP_DELCOL
Definition: excdefs.hxx:70
virtual sal_uInt16 GetNum() const override
sal_uInt16 GetId(sal_uInt16 nIndex) const
void PushActionRecord(const ScChangeAction &rAction)
SCCOL Col() const
Definition: address.hxx:266
const XclExpRoot & GetRoot() const
Returns this root instance - for code readability in derived classes.
Definition: xeroot.hxx:118
virtual void Save(XclExpStream &rStrm) override
Writes the record header and calls WriteBody().
#define EXC_CHTR_TYPE_FORMULA
Definition: excdefs.hxx:85
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:684
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:90
XclExpStringRef mpFormattedString
std::map< sal_uLong, ScChangeAction * > ScChangeActionMap
Definition: chgtrack.hxx:805
XclExpChangeTrack(const XclExpRoot &rRoot)
ScBigAddress aStart
Definition: bigrange.hxx:110
XclExpChTrTabIdBuffer(sal_uInt16 nCount)
sal_Int32 Tab() const
Definition: bigrange.hxx:48
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:118
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:74
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:61
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:249
virtual void SaveXml(XclExpXmlStream &rStrm) override
std::vector< XclExpUserBView > aViews
sal_uInt8 aGUID[16]
XclExpUserBView(const OUString &rUsername, const sal_uInt8 *pGUID)
std::vector< sal_uInt16 > maTabBuffer
#define EXC_CHTR_OP_UNKNOWN
Definition: excdefs.hxx:75
const ScAddress & GetXclMaxPos() const
Returns the highest possible cell address in an Excel document (using current BIFF version)...
Definition: xlroot.hxx:244
#define EXC_CHTR_TYPE_STRING
Definition: excdefs.hxx:83
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:33
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:68
XclExpString sUsername
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:400
#define EXC_CHTR_OP_INSROW
Definition: excdefs.hxx:67
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:31
EditTextObject * mpEditText
Definition: cellvalue.hxx:41
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:71
const ScFormulaCell * mpFormulaCell
std::unique_ptr< XclExpChTrData > pNewData
const std::set< OUString > & GetUserCollection() const
Definition: chgtrack.hxx:978
static SC_DLLPUBLIC OUString GetString(const EditTextObject &rEditText, const ScDocument *pDoc)
Retrieves string with paragraphs delimited by new lines (' ').
Definition: editutil.cxx:111
std::unique_ptr< XclExpString > pString
void EnableEncryption(bool bEnable=true)
Definition: xestream.cxx:359
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:4374
const ScCellValue & GetNewCell() const
Definition: chgtrack.hxx:746
virtual ~XclExpChTr0x0195() override
#define EXC_CHTR_ACCEPT
Definition: excdefs.hxx:89
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:3815
void SetCount(sal_uInt32 nNew)
SC_DLLPUBLIC void GetDelta(sal_Int32 &nDx, sal_Int32 &nDy, sal_Int32 &nDz) const
Definition: chgtrack.cxx:1136
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:121
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:244
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:22
void WriteZeroBytes(std::size_t nBytes)
Writes a sequence of nBytes zero bytes (respects slice setting).
Definition: xestream.cxx:257
virtual sal_uInt16 GetNum() const override
virtual void SaveXml(XclExpXmlStream &rStrm) override