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

Generated by: LCOV version 1.11