[Libreoffice-commits] core.git: Branch 'libreoffice-4-3' - sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Sat Jul 19 02:04:42 PDT 2014


 sc/source/filter/excel/xestream.cxx          |    7 
 sc/source/filter/inc/XclExpChangeTrack.hxx   |   78 ++++--
 sc/source/filter/inc/xestream.hxx            |   10 
 sc/source/filter/xcl97/XclExpChangeTrack.cxx |  337 +++++++++++++++++----------
 4 files changed, 289 insertions(+), 143 deletions(-)

New commits:
commit 6ace1e560373284a116c645bca82ff78ef112576
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Jul 17 20:20:16 2014 -0400

    bnc#885548: Adjust xlsx export of revisions to get it to work in Excel.
    
    (cherry picked from commit fa44673e154ed4fb0b518b8850e2f6e4b9069531)
    
    Conflicts:
    	sc/source/filter/inc/XclExpChangeTrack.hxx
    	sc/source/filter/xcl97/XclExpChangeTrack.cxx
    
    Change-Id: I0058d9ddfea545390e615a3030171a366e333c85
    Reviewed-on: https://gerrit.libreoffice.org/10394
    Reviewed-by: Markus Mohrhard <markus.mohrhard at googlemail.com>
    Tested-by: Markus Mohrhard <markus.mohrhard at googlemail.com>

diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx
index 6f5c7b4..b9cb8b1 100644
--- a/sc/source/filter/excel/xestream.cxx
+++ b/sc/source/filter/excel/xestream.cxx
@@ -836,6 +836,13 @@ const char* XclXmlUtils::ToPsz( bool b )
     return b ? "true" : "false";
 }
 
+const char* XclXmlUtils::ToPsz10( bool b )
+{
+    // xlsx seems to use "1" or "0" for boolean values.  I wonder it ever uses
+    // the "true" "false" variant.
+    return b ? "1" : "0";
+}
+
 sax_fastparser::FSHelperPtr XclXmlUtils::WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, sal_Int32 nValue )
 {
     pStream->startElement( nElement, FSEND );
diff --git a/sc/source/filter/inc/XclExpChangeTrack.hxx b/sc/source/filter/inc/XclExpChangeTrack.hxx
index 695d694..7ed0dbe 100644
--- a/sc/source/filter/inc/XclExpChangeTrack.hxx
+++ b/sc/source/filter/inc/XclExpChangeTrack.hxx
@@ -29,6 +29,15 @@
 #include "ftools.hxx"
 #include "excrecds.hxx"
 
+#include <boost/ptr_container/ptr_vector.hpp>
+
+class ExcXmlRecord : public ExcRecord
+{
+public:
+    virtual sal_Size    GetLen() const SAL_OVERRIDE;
+    virtual sal_uInt16  GetNum() const SAL_OVERRIDE;
+    virtual void        Save( XclExpStream& rStrm ) SAL_OVERRIDE;
+};
 
 // XclExpUserBView - one UserBView record for each user
 
@@ -238,6 +247,39 @@ public:
     virtual void                SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
 };
 
+class XclExpXmlChTrHeaders : public ExcXmlRecord
+{
+    sal_uInt8 maGUID[16];
+public:
+    void SetGUID( const sal_uInt8* pGUID );
+
+    virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+};
+
+class XclExpChTrTabIdBuffer;
+class XclExpChTrAction;
+
+class XclExpXmlChTrHeader : public ExcXmlRecord
+{
+    OUString maUserName;
+    DateTime maDateTime;
+    sal_uInt8 maGUID[16];
+    sal_Int32 mnLogNumber;
+    sal_uInt32 mnMinAction;
+    sal_uInt32 mnMaxAction;
+
+    std::vector<sal_uInt16> maTabBuffer;
+    std::vector<XclExpChTrAction*> maActions;
+
+public:
+    XclExpXmlChTrHeader(
+        const OUString& rUserName, const DateTime& rDateTime, const sal_uInt8* pGUID,
+        sal_Int32 nLogNumber, const XclExpChTrTabIdBuffer& rBuf );
+
+    virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
+    void AppendAction( XclExpChTrAction* pAction );
+};
 
 // XclExpChTrInfo - header of action group of a user
 
@@ -245,35 +287,21 @@ class XclExpChTrInfo : public ExcRecord
 {
 private:
     XclExpString                sUsername;
-    sal_Int32                   mnLogNumber;
     DateTime                    aDateTime;
     sal_uInt8                   aGUID[ 16 ];
 
     virtual void                SaveCont( XclExpStream& rStrm ) SAL_OVERRIDE;
 
 public:
-    inline                      XclExpChTrInfo(
-                                    const OUString& rUsername,
-                                    const DateTime& rDateTime,
-                                    const sal_uInt8* pGUID,
-                                    sal_Int32 nLogNumber );
+    XclExpChTrInfo( const OUString& rUsername, const DateTime& rDateTime,
+                    const sal_uInt8* pGUID );
+
     virtual                     ~XclExpChTrInfo();
 
     virtual sal_uInt16              GetNum() const SAL_OVERRIDE;
     virtual sal_Size            GetLen() const SAL_OVERRIDE;
-
-    virtual void                SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
 };
 
-inline XclExpChTrInfo::XclExpChTrInfo( const OUString& rUsername, const DateTime& rDateTime, const sal_uInt8* pGUID, sal_Int32 nLogNumber ) :
-    sUsername( rUsername ),
-    mnLogNumber( nLogNumber ),
-    aDateTime( rDateTime )
-{
-    memcpy( aGUID, pGUID, 16 );
-}
-
-
 // XclExpChTrTabIdBuffer - buffer for tab id's
 
 class XclExpChTrTabIdBuffer
@@ -309,7 +337,6 @@ class XclExpChTrTabId : public ExcRecord
 private:
     sal_uInt16*                 pBuffer;
     sal_uInt16                  nTabCount;
-    bool                        mbInRevisionHeaders;
 
     inline void                 Clear() { if( pBuffer ) delete[] pBuffer; pBuffer = NULL; }
 
@@ -317,16 +344,14 @@ private:
 
 public:
     inline                      XclExpChTrTabId( sal_uInt16 nCount ) :
-                                    pBuffer( NULL ), nTabCount( nCount ), mbInRevisionHeaders( false ) {}
-                                XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer, bool bInRevisionHeaders = false );
+                                    pBuffer( NULL ), nTabCount( nCount ) {}
+                                XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer );
     virtual                     ~XclExpChTrTabId();
 
     void                        Copy( const XclExpChTrTabIdBuffer& rBuffer );
 
     virtual sal_uInt16              GetNum() const SAL_OVERRIDE;
     virtual sal_Size            GetLen() const SAL_OVERRIDE;
-
-    virtual void                SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
 };
 
 
@@ -375,7 +400,6 @@ protected:
                                 // do something after writing the record
     virtual void                CompleteSaveAction( XclExpStream& rStrm ) const;
 
-    inline sal_uInt32           GetActionNumber() const { return nIndex; }
     inline bool                 GetAccepted() const { return bAccepted; }
 
 public:
@@ -399,6 +423,7 @@ public:
     virtual sal_Size            GetLen() const SAL_OVERRIDE;
 
     inline XclExpChTrAction*    GetAddAction() { return pAddAction; }
+    inline sal_uInt32           GetActionNumber() const { return nIndex; }
 };
 
 inline void XclExpChTrAction::Write2DAddress( XclExpStream& rStrm, const ScAddress& rAddress ) const
@@ -590,11 +615,12 @@ public:
 
 class XclExpChangeTrack : protected XclExpRoot
 {
-private:
-    std::vector<ExcRecord*>       aRecList;           // list of "Revision Log" stream records
+    typedef boost::ptr_vector<ExcRecord> RecListType;
+    typedef boost::ptr_vector<XclExpChTrTabIdBuffer> TabIdBufferType;
+    RecListType maRecList;           // list of "Revision Log" stream records
     std::stack<XclExpChTrAction*> aActionStack;
     XclExpChTrTabIdBuffer*        pTabIdBuffer;
-    std::vector<XclExpChTrTabIdBuffer*> maBuffers;
+    TabIdBufferType maBuffers;
 
     ScDocument*                 pTempDoc;           // empty document
 
diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx
index 3d36c04..67ac922 100644
--- a/sc/source/filter/inc/xestream.hxx
+++ b/sc/source/filter/inc/xestream.hxx
@@ -280,8 +280,18 @@ public:
     static OUString ToOUString( const ScfUInt16Vec& rBuffer, sal_Int32 nStart = 0, sal_Int32 nLength = -1 );
     static OUString ToOUString( ScDocument& rDocument, const ScAddress& rAddress, const ScTokenArray* pTokenArray );
     static OUString ToOUString( const XclExpString& s );
+
+    /**
+     * @return const char* literal "true" for true value, or literal "false"
+     *         for false value.
+     */
     static const char* ToPsz( bool b );
 
+    /**
+     * @return literal "1" for true value, or literal "0" for false value.
+     */
+    static const char* ToPsz10( bool b );
+
     static sax_fastparser::FSHelperPtr  WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, sal_Int32 nValue );
     static sax_fastparser::FSHelperPtr  WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, sal_Int64 nValue );
     static sax_fastparser::FSHelperPtr  WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, const char* sValue );
diff --git a/sc/source/filter/xcl97/XclExpChangeTrack.cxx b/sc/source/filter/xcl97/XclExpChangeTrack.cxx
index 4546a1d..93b5a09 100644
--- a/sc/source/filter/xcl97/XclExpChangeTrack.cxx
+++ b/sc/source/filter/xcl97/XclExpChangeTrack.cxx
@@ -38,7 +38,7 @@ static OString lcl_GuidToOString( sal_uInt8 aGuid[ 16 ] )
 {
     char sBuf[ 40 ];
     snprintf( sBuf, sizeof( sBuf ),
-            "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
+            "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
             aGuid[ 0 ], aGuid[ 1 ], aGuid[ 2 ], aGuid[ 3 ], aGuid[ 4 ], aGuid[ 5 ], aGuid[ 6 ], aGuid[ 7 ],
             aGuid[ 8 ], aGuid[ 9 ], aGuid[ 10 ], aGuid[ 11 ], aGuid[ 12 ], aGuid[ 13 ], aGuid[ 14 ], aGuid[ 15 ] );
     return OString( sBuf );
@@ -368,6 +368,150 @@ void XclExpChTrHeader::SaveXml( XclExpXmlStream& rRevisionHeadersStrm )
     pHeaders->write( ">" );
 }
 
+void XclExpXmlChTrHeaders::SetGUID( const sal_uInt8* pGUID )
+{
+    memcpy(maGUID, pGUID, 16);
+}
+
+void XclExpXmlChTrHeaders::SaveXml( XclExpXmlStream& rStrm )
+{
+    sax_fastparser::FSHelperPtr pHeaders = rStrm.GetCurrentStream();
+
+    pHeaders->write("<")->writeId(XML_headers);
+
+    rStrm.WriteAttributes(
+        XML_xmlns,              "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
+        FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
+        XML_guid,               lcl_GuidToOString(maGUID).getStr(),
+        XML_lastGuid,           NULL,   // OOXTODO
+        XML_shared,             NULL,   // OOXTODO
+        XML_diskRevisions,      NULL,   // OOXTODO
+        XML_history,            NULL,   // OOXTODO
+        XML_trackRevisions,     NULL,   // OOXTODO
+        XML_exclusive,          NULL,   // OOXTODO
+        XML_revisionId,         NULL,   // OOXTODO
+        XML_version,            NULL,   // OOXTODO
+        XML_keepChangeHistory,  NULL,   // OOXTODO
+        XML_protected,          NULL,   // OOXTODO
+        XML_preserveHistory,    NULL,   // OOXTODO
+        FSEND);
+
+    pHeaders->write(">");
+}
+
+XclExpXmlChTrHeader::XclExpXmlChTrHeader(
+    const OUString& rUserName, const DateTime& rDateTime, const sal_uInt8* pGUID,
+    sal_Int32 nLogNumber, const XclExpChTrTabIdBuffer& rBuf ) :
+    maUserName(rUserName), maDateTime(rDateTime), mnLogNumber(nLogNumber),
+    mnMinAction(0), mnMaxAction(0)
+{
+    memcpy(maGUID, pGUID, 16);
+    if (rBuf.GetBufferCount())
+    {
+        maTabBuffer.resize(rBuf.GetBufferCount());
+        rBuf.GetBufferCopy(&maTabBuffer[0]);
+    }
+}
+
+void XclExpXmlChTrHeader::SaveXml( XclExpXmlStream& rStrm )
+{
+    sax_fastparser::FSHelperPtr pHeader = rStrm.GetCurrentStream();
+
+    pHeader->write("<")->writeId(XML_header);
+
+    OUString aRelId;
+    sax_fastparser::FSHelperPtr pRevLogStrm = rStrm.CreateOutputStream(
+            XclXmlUtils::GetStreamName("xl/revisions/", "revisionLog", mnLogNumber),
+            XclXmlUtils::GetStreamName(NULL, "revisionLog", mnLogNumber),
+            rStrm.GetCurrentStream()->getOutputStream(),
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml",
+            CREATE_OFFICEDOC_RELATION_TYPE("revisionLog"),
+            &aRelId);
+
+    rStrm.WriteAttributes(
+        XML_guid, lcl_GuidToOString(maGUID).getStr(),
+        XML_dateTime, lcl_DateTimeToOString(maDateTime).getStr(),
+        XML_userName, XclXmlUtils::ToOString(maUserName).getStr(),
+        FSNS(XML_r, XML_id),  XclXmlUtils::ToOString(aRelId).getStr(),
+        FSEND);
+
+    if (mnMinAction)
+        rStrm.WriteAttributes(XML_minRId, OString::number(mnMinAction).getStr(), FSEND);
+
+    if (mnMaxAction)
+        rStrm.WriteAttributes(XML_maxRId, OString::number(mnMaxAction).getStr(), FSEND);
+
+    if (!maTabBuffer.empty())
+        // next available sheet index.
+        rStrm.WriteAttributes(XML_maxSheetId, OString::number(maTabBuffer.back()+1).getStr(), FSEND);
+
+    pHeader->write(">");
+
+    if (!maTabBuffer.empty())
+    {
+        // Write sheet index map.
+        size_t n = maTabBuffer.size();
+        pHeader->startElement(
+            XML_sheetIdMap,
+            XML_count, OString::number(n).getStr(),
+            FSEND);
+
+        for (size_t i = 0; i < n; ++i)
+        {
+            pHeader->singleElement(
+                XML_sheetId,
+                XML_val, OString::number(maTabBuffer[i]).getStr(),
+                FSEND);
+        }
+        pHeader->endElement(XML_sheetIdMap);
+    }
+
+    // Write all revision logs in a separate stream.
+
+    rStrm.PushStream(pRevLogStrm);
+
+    pRevLogStrm->write("<")->writeId(XML_revisions);
+
+    rStrm.WriteAttributes(
+        XML_xmlns,              "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
+        FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
+        FSEND);
+
+    pRevLogStrm->write(">");
+
+    std::vector<XclExpChTrAction*>::iterator it = maActions.begin(), itEnd = maActions.end();
+    for (; it != itEnd; ++it)
+    {
+        XclExpChTrAction* p = *it;
+        p->SaveXml(rStrm);
+    }
+
+    pRevLogStrm->write("</")->writeId(XML_revisions)->write(">");
+
+    rStrm.PopStream();
+
+    pHeader->write("</")->writeId(XML_header)->write(">");
+}
+
+void XclExpXmlChTrHeader::AppendAction( XclExpChTrAction* pAction )
+{
+    sal_uInt32 nActionNum = pAction->GetActionNumber();
+    if (!mnMinAction || mnMinAction > nActionNum)
+        mnMinAction = nActionNum;
+
+    if (!mnMaxAction || mnMaxAction < nActionNum)
+        mnMaxAction = nActionNum;
+
+    maActions.push_back(pAction);
+}
+
+XclExpChTrInfo::XclExpChTrInfo( const OUString& rUsername, const DateTime& rDateTime, const sal_uInt8* pGUID ) :
+    sUsername( rUsername ),
+    aDateTime( rDateTime )
+{
+    memcpy( aGUID, pGUID, 16 );
+}
+
 XclExpChTrInfo::~XclExpChTrInfo()
 {
 }
@@ -396,33 +540,6 @@ sal_Size XclExpChTrInfo::GetLen() const
     return 158;
 }
 
-void XclExpChTrInfo::SaveXml( XclExpXmlStream& rRevisionHeadersStrm )
-{
-    sax_fastparser::FSHelperPtr pHeader = rRevisionHeadersStrm.GetCurrentStream();
-
-    OUString sRelationshipId;
-    sax_fastparser::FSHelperPtr pRevisionLog = rRevisionHeadersStrm.CreateOutputStream(
-            XclXmlUtils::GetStreamName( "xl/revisions/", "revisionLog", mnLogNumber ),
-            XclXmlUtils::GetStreamName( NULL, "revisionLog", mnLogNumber ),
-            rRevisionHeadersStrm.GetCurrentStream()->getOutputStream(),
-            "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml",
-            "http://schemas.openxmlformats.org/officeDocument/2006/relationships/revisionLog",
-            &sRelationshipId );
-
-    rRevisionHeadersStrm.WriteAttributes(
-            XML_guid,               lcl_GuidToOString( aGUID ).getStr(),
-            XML_dateTime,           lcl_DateTimeToOString( aDateTime ).getStr(),
-            XML_maxSheetId,         NULL,   // OOXTODO
-            XML_userName,           XclXmlUtils::ToOString( sUsername ).getStr(),
-            FSNS( XML_r, XML_id ),  XclXmlUtils::ToOString( sRelationshipId ).getStr(),
-            XML_minRId,             NULL,   // OOXTODO
-            XML_maxRId,             NULL,   // OOXTODO
-            FSEND );
-    pHeader->write( ">" );
-
-    rRevisionHeadersStrm.PushStream( pRevisionLog );
-}
-
 XclExpChTrTabIdBuffer::XclExpChTrTabIdBuffer( sal_uInt16 nCount ) :
     nBufSize( nCount ),
     nLastId( nCount )
@@ -493,9 +610,8 @@ void XclExpChTrTabIdBuffer::Remove()
     nLastId--;
 }
 
-XclExpChTrTabId::XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer, bool bInRevisionHeaders )
+XclExpChTrTabId::XclExpChTrTabId( const XclExpChTrTabIdBuffer& rBuffer )
     : nTabCount( rBuffer.GetBufferCount() )
-    , mbInRevisionHeaders( bInRevisionHeaders )
 {
     pBuffer = new sal_uInt16[ nTabCount ];
     rBuffer.GetBufferCopy( pBuffer );
@@ -535,29 +651,6 @@ sal_Size XclExpChTrTabId::GetLen() const
     return nTabCount << 1;
 }
 
-void XclExpChTrTabId::SaveXml( XclExpXmlStream& rRevisionLogStrm )
-{
-    if( !mbInRevisionHeaders )
-        return;
-
-    sax_fastparser::FSHelperPtr pRevisionLog = rRevisionLogStrm.GetCurrentStream();
-    rRevisionLogStrm.PopStream();
-
-    sax_fastparser::FSHelperPtr pHeader = rRevisionLogStrm.GetCurrentStream();
-    pHeader->startElement( XML_sheetIdMap,
-            XML_count,  OString::number( nTabCount ).getStr(),
-            FSEND );
-    for( int i = 0; i < nTabCount; ++i )
-    {
-        pHeader->singleElement( XML_sheetId,
-                XML_val,    OString::number( pBuffer[ i ] ).getStr(),
-                FSEND );
-    }
-    pHeader->endElement( XML_sheetIdMap );
-
-    rRevisionLogStrm.PushStream( pRevisionLog );
-}
-
 // ! does not copy additional actions
 XclExpChTrAction::XclExpChTrAction( const XclExpChTrAction& rCopy ) :
     ExcRecord( rCopy ),
@@ -1099,11 +1192,12 @@ void XclExpChTrInsert::SaveXml( XclExpXmlStream& rRevisionLogStrm )
             XML_ua,     XclXmlUtils::ToPsz( GetAccepted () ),   // OOXTODO? bAccepted == ua or ra; not sure.
             XML_ra,     NULL,       // OOXTODO: RRD.fUndoAction?  Or RRD.fAccepted?
             XML_sId,    OString::number(  GetTabId( aRange.aStart.Tab() ) ).getStr(),
-            XML_eol,    NULL,       // OOXTODO: not supported?
+            XML_eol,    XclXmlUtils::ToPsz10(mbEndOfList),
             XML_ref,    XclXmlUtils::ToOString( aRange ).getStr(),
             XML_action, lcl_GetAction( nOpCode ),
             XML_edge,   NULL,       // OOXTODO: ???
             FSEND );
+
     // OOXTODO: does this handle XML_rfmt, XML_undo?
     XclExpChTrAction* pAction = GetAddAction();
     while( pAction != NULL )
@@ -1285,14 +1379,6 @@ void XclExpChTr0x014A::SaveXml( XclExpXmlStream& rStrm )
     pStream->endElement( XML_rfmt );
 }
 
-class ExcXmlRecord : public ExcRecord
-{
-public:
-    virtual sal_Size    GetLen() const SAL_OVERRIDE;
-    virtual sal_uInt16  GetNum() const SAL_OVERRIDE;
-    virtual void        Save( XclExpStream& rStrm ) SAL_OVERRIDE;
-};
-
 sal_Size ExcXmlRecord::GetLen() const
 {
     return 0;
@@ -1412,66 +1498,83 @@ XclExpChangeTrack::XclExpChangeTrack( const XclExpRoot& rRoot ) :
     }
 
     // build record list
-    pHeader = new XclExpChTrHeader;
-    aRecList.push_back( new StartXmlElement( XML_headers, StartXmlElement::WRITE_NAMESPACES ) );
-    aRecList.push_back( pHeader );
-    aRecList.push_back( new XclExpChTr0x0195 );
-    aRecList.push_back( new XclExpChTr0x0194( *pTempChangeTrack ) );
-
-    OUString sLastUsername;
-    DateTime aLastDateTime( DateTime::EMPTY );
-    sal_uInt32 nIndex = 1;
-    sal_Int32 nLogNumber = 1;
-    while( !aActionStack.empty() )
+    if (GetOutput() == EXC_OUTPUT_BINARY)
     {
-        XclExpChTrAction* pAction = aActionStack.top();
-        aActionStack.pop();
-
-        if( (nIndex == 1) || pAction->ForceInfoRecord() ||
-            (pAction->GetUsername() != sLastUsername) ||
-            (pAction->GetDateTime() != aLastDateTime) )
+        pHeader = new XclExpChTrHeader;
+        maRecList.push_back( pHeader );
+        maRecList.push_back( new XclExpChTr0x0195 );
+        maRecList.push_back( new XclExpChTr0x0194( *pTempChangeTrack ) );
+
+        OUString sLastUsername;
+        DateTime aLastDateTime( DateTime::EMPTY );
+        sal_uInt32 nIndex = 1;
+        sal_Int32 nLogNumber = 1;
+        while( !aActionStack.empty() )
         {
-            if( nIndex != 1 )
+            XclExpChTrAction* pAction = aActionStack.top();
+            aActionStack.pop();
+
+            if( (nIndex == 1) || pAction->ForceInfoRecord() ||
+                (pAction->GetUsername() != sLastUsername) ||
+                (pAction->GetDateTime() != aLastDateTime) )
             {
-                aRecList.push_back( new EndXmlElement( XML_revisions ) );
-                aRecList.push_back( new EndHeaderElement() );
+                lcl_GenerateGUID( aGUID, bValidGUID );
+                sLastUsername = pAction->GetUsername();
+                aLastDateTime = pAction->GetDateTime();
+
+                nLogNumber++;
+                maRecList.push_back( new XclExpChTrInfo(sLastUsername, aLastDateTime, aGUID) );
+                maRecList.push_back( new XclExpChTrTabId(pAction->GetTabIdBuffer()) );
+                pHeader->SetGUID( aGUID );
             }
+            pAction->SetIndex( nIndex );
+            maRecList.push_back( pAction );
+        }
 
-            lcl_GenerateGUID( aGUID, bValidGUID );
-            sLastUsername = pAction->GetUsername();
-            aLastDateTime = pAction->GetDateTime();
+        pHeader->SetGUID( aGUID );
+        pHeader->SetCount( nIndex - 1 );
+        maRecList.push_back( new ExcEof );
+    }
+    else
+    {
+        XclExpXmlChTrHeaders* pHeaders = new XclExpXmlChTrHeaders;
+        maRecList.push_back(pHeaders);
+
+        OUString sLastUsername;
+        DateTime aLastDateTime(DateTime::EMPTY);
+        sal_uInt32 nIndex = 1;
+        sal_Int32 nLogNumber = 1;
+        XclExpXmlChTrHeader* pCurHeader = NULL;
 
-            aRecList.push_back( new StartXmlElement( XML_header, 0 ) );
-            aRecList.push_back( new XclExpChTrInfo( sLastUsername, aLastDateTime, aGUID, nLogNumber++ ) );
-            aRecList.push_back( new XclExpChTrTabId( pAction->GetTabIdBuffer(), true ) );
-            aRecList.push_back( new StartXmlElement( XML_revisions, StartXmlElement::WRITE_NAMESPACES | StartXmlElement::CLOSE_ELEMENT ) );
-            pHeader->SetGUID( aGUID );
+        while (!aActionStack.empty())
+        {
+            XclExpChTrAction* pAction = aActionStack.top();
+            aActionStack.pop();
+
+            if( (nIndex == 1) || pAction->ForceInfoRecord() ||
+                (pAction->GetUsername() != sLastUsername) ||
+                (pAction->GetDateTime() != aLastDateTime) )
+            {
+                lcl_GenerateGUID( aGUID, bValidGUID );
+                sLastUsername = pAction->GetUsername();
+                aLastDateTime = pAction->GetDateTime();
+
+                pCurHeader = new XclExpXmlChTrHeader(sLastUsername, aLastDateTime, aGUID, nLogNumber, pAction->GetTabIdBuffer());
+                maRecList.push_back(pCurHeader);
+                nLogNumber++;
+                pHeaders->SetGUID(aGUID);
+            }
+            pAction->SetIndex(nIndex);
+            pCurHeader->AppendAction(pAction);
         }
-        pAction->SetIndex( nIndex );
-        aRecList.push_back( pAction );
-    }
 
-    pHeader->SetGUID( aGUID );
-    pHeader->SetCount( nIndex - 1 );
-    if( nLogNumber > 1 )
-    {
-        aRecList.push_back( new EndXmlElement( XML_revisions ) );
-        aRecList.push_back( new EndHeaderElement() );
+        pHeaders->SetGUID(aGUID);
+        maRecList.push_back(new EndXmlElement(XML_headers));
     }
-    aRecList.push_back( new EndXmlElement( XML_headers ) );
-    aRecList.push_back( new ExcEof );
 }
 
 XclExpChangeTrack::~XclExpChangeTrack()
 {
-    std::vector<ExcRecord*>::iterator prIter;
-    for ( prIter = aRecList.begin(); prIter != aRecList.end(); ++prIter )
-        delete *prIter;
-
-    std::vector<XclExpChTrTabIdBuffer*>::iterator pIter;
-    for ( pIter = maBuffers.begin(); pIter != maBuffers.end(); ++pIter )
-        delete *pIter;
-
     while( !aActionStack.empty() )
     {
         delete aActionStack.top();
@@ -1567,7 +1670,7 @@ bool XclExpChangeTrack::WriteUserNamesStream()
 
 void XclExpChangeTrack::Write()
 {
-    if( aRecList.empty() )
+    if (maRecList.empty())
         return;
 
     if( WriteUserNamesStream() )
@@ -1578,9 +1681,9 @@ void XclExpChangeTrack::Write()
         {
             XclExpStream aXclStrm( *xSvStrm, GetRoot(), EXC_MAXRECSIZE_BIFF8 + 8 );
 
-            std::vector<ExcRecord*>::iterator pIter;
-            for ( pIter = aRecList.begin(); pIter != aRecList.end(); ++pIter )
-                (*pIter)->Save(aXclStrm);
+            RecListType::iterator pIter;
+            for (pIter = maRecList.begin(); pIter != maRecList.end(); ++pIter)
+                pIter->Save(aXclStrm);
 
             xSvStrm->Commit();
         }
@@ -1608,7 +1711,7 @@ static void lcl_WriteUserNamesXml( XclExpXmlStream& rWorkbookStrm )
 
 void XclExpChangeTrack::WriteXml( XclExpXmlStream& rWorkbookStrm )
 {
-    if( aRecList.empty() )
+    if (maRecList.empty())
         return;
 
     lcl_WriteUserNamesXml( rWorkbookStrm );
@@ -1624,9 +1727,9 @@ void XclExpChangeTrack::WriteXml( XclExpXmlStream& rWorkbookStrm )
     //          contents of XclExpChangeTrack::WriteUserNamesStream()).
     rWorkbookStrm.PushStream( pRevisionHeaders );
 
-    std::vector<ExcRecord*>::iterator pIter;
-    for ( pIter = aRecList.begin(); pIter != aRecList.end(); ++pIter )
-        (*pIter)->SaveXml(rWorkbookStrm);
+    RecListType::iterator pIter;
+    for (pIter = maRecList.begin(); pIter != maRecList.end(); ++pIter)
+        pIter->SaveXml(rWorkbookStrm);
 
     rWorkbookStrm.PopStream();
 }


More information about the Libreoffice-commits mailing list