LCOV - code coverage report
Current view: top level - sc/source/filter/xcl97 - XclExpChangeTrack.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 672 879 76.5 %
Date: 2014-11-03 Functions: 119 158 75.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10