summaryrefslogtreecommitdiff
path: root/sc/source/filter/xcl97/XclImpChangeTrack.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/xcl97/XclImpChangeTrack.cxx')
-rw-r--r--sc/source/filter/xcl97/XclImpChangeTrack.cxx502
1 files changed, 502 insertions, 0 deletions
diff --git a/sc/source/filter/xcl97/XclImpChangeTrack.cxx b/sc/source/filter/xcl97/XclImpChangeTrack.cxx
new file mode 100644
index 000000000000..96a301e1bef5
--- /dev/null
+++ b/sc/source/filter/xcl97/XclImpChangeTrack.cxx
@@ -0,0 +1,502 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+#include "XclImpChangeTrack.hxx"
+#include <tools/debug.hxx>
+#include <sot/storage.hxx>
+#include <svl/zforlist.hxx>
+#include "chgviset.hxx"
+#include "cell.hxx"
+#include "chgtrack.hxx"
+#include "xihelper.hxx"
+#include "xilink.hxx"
+#include "externalrefmgr.hxx"
+
+//___________________________________________________________________
+// class XclImpChangeTrack
+
+XclImpChangeTrack::XclImpChangeTrack( const XclImpRoot& rRoot, const XclImpStream& rBookStrm ) :
+ XclImpRoot( rRoot ),
+ aRecHeader(),
+ sOldUsername(),
+ pChangeTrack( NULL ),
+ pStrm( NULL ),
+ nTabIdCount( 0 ),
+ bGlobExit( sal_False ),
+ eNestedMode( nmBase )
+{
+ // Verify that the User Names stream exists before going any further. Excel adds both
+ // "Revision Log" and "User Names" streams when Change Tracking is active but the Revision log
+ // remains if Change Tracking is turned off.
+ SotStorageStreamRef xUserStrm = OpenStream( EXC_STREAM_USERNAMES );
+ if( !xUserStrm.Is() )
+ return;
+
+ xInStrm = OpenStream( EXC_STREAM_REVLOG );
+ if( xInStrm.Is() )
+ {
+ xInStrm->Seek( STREAM_SEEK_TO_END );
+ ULONG nStreamLen = xInStrm->Tell();
+ if( (xInStrm->GetErrorCode() == ERRCODE_NONE) && (nStreamLen != STREAM_SEEK_TO_END) )
+ {
+ xInStrm->Seek( STREAM_SEEK_TO_BEGIN );
+ pStrm = new XclImpStream( *xInStrm, GetRoot() );
+ pStrm->CopyDecrypterFrom( rBookStrm );
+ pChangeTrack = new ScChangeTrack( GetDocPtr() );
+
+ sOldUsername = pChangeTrack->GetUser();
+ pChangeTrack->SetUseFixDateTime( TRUE );
+
+ ReadRecords();
+ }
+ }
+}
+
+XclImpChangeTrack::~XclImpChangeTrack()
+{
+ delete pChangeTrack;
+ delete pStrm;
+}
+
+void XclImpChangeTrack::DoAcceptRejectAction( ScChangeAction* pAction )
+{
+ if( !pAction ) return;
+ switch( aRecHeader.nAccept )
+ {
+ case EXC_CHTR_ACCEPT:
+ pChangeTrack->Accept( pAction );
+ break;
+ case EXC_CHTR_REJECT:
+ break;
+ }
+}
+
+void XclImpChangeTrack::DoAcceptRejectAction( sal_uInt32 nFirst, sal_uInt32 nLast )
+{
+ for( sal_uInt32 nIndex = nFirst; nIndex <= nLast; nIndex++ )
+ DoAcceptRejectAction( pChangeTrack->GetAction( nIndex ) );
+}
+
+void XclImpChangeTrack::DoInsertRange( const ScRange& rRange )
+{
+ sal_uInt32 nFirst = pChangeTrack->GetActionMax() + 1;
+ pChangeTrack->AppendInsert( rRange );
+ sal_uInt32 nLast = pChangeTrack->GetActionMax();
+ DoAcceptRejectAction( nFirst, nLast );
+}
+
+void XclImpChangeTrack::DoDeleteRange( const ScRange& rRange )
+{
+ ULONG nFirst, nLast;
+ pChangeTrack->AppendDeleteRange( rRange, NULL, nFirst, nLast );
+ DoAcceptRejectAction( nFirst, nLast );
+}
+
+SCTAB XclImpChangeTrack::ReadTabNum()
+{
+ return static_cast<SCTAB>(GetTabInfo().GetCurrentIndex(
+ pStrm->ReaduInt16(), nTabIdCount ));
+}
+
+void XclImpChangeTrack::ReadDateTime( DateTime& rDateTime )
+{
+ sal_uInt16 nYear;
+ sal_uInt8 nMonth, nDay, nHour, nMin, nSec;
+
+ *pStrm >> nYear >> nMonth >> nDay >> nHour >> nMin >> nSec;
+
+ rDateTime.SetYear( nYear );
+ rDateTime.SetMonth( nMonth );
+ rDateTime.SetDay( nDay );
+ rDateTime.SetHour( nHour );
+ rDateTime.SetMin( nMin );
+ rDateTime.SetSec( nSec );
+ rDateTime.Set100Sec( 0 );
+}
+
+sal_Bool XclImpChangeTrack::CheckRecord( sal_uInt16 nOpCode )
+{
+ if( (nOpCode != EXC_CHTR_OP_UNKNOWN) && (aRecHeader.nOpCode != nOpCode) )
+ {
+ DBG_ERROR( "XclImpChangeTrack::CheckRecord - unknown action" );
+ return sal_False;
+ }
+ return aRecHeader.nIndex != 0;
+}
+
+sal_Bool XclImpChangeTrack::Read3DTabRefInfo( SCTAB& rFirstTab, SCTAB& rLastTab, ExcelToSc8::ExternalTabInfo& rExtInfo )
+{
+ if( LookAtuInt8() == 0x01 )
+ {
+ rExtInfo.mbExternal = false;
+ // internal ref - read tab num and return sc tab num (position in TABID list)
+ pStrm->Ignore( 3 );
+ rFirstTab = static_cast< SCTAB >( GetTabInfo().GetCurrentIndex( pStrm->ReaduInt16(), nTabIdCount ) );
+ sal_uInt8 nFillByte = pStrm->ReaduInt8();
+ rLastTab = (nFillByte == 0x00) ?
+ static_cast< SCTAB >( GetTabInfo().GetCurrentIndex( pStrm->ReaduInt16(), nTabIdCount ) ) : rFirstTab;
+ }
+ else
+ {
+ // external ref - read doc and tab name and find sc tab num
+ // - URL
+ String aEncUrl( pStrm->ReadUniString() );
+ String aUrl;
+ bool bSelf;
+ XclImpUrlHelper::DecodeUrl( aUrl, bSelf, GetRoot(), aEncUrl );
+ pStrm->Ignore( 1 );
+ // - sheet name, always separated from URL
+ String aTabName( pStrm->ReadUniString() );
+ pStrm->Ignore( 1 );
+
+ rExtInfo.mbExternal = true;
+ ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
+ pRefMgr->convertToAbsName(aUrl);
+ rExtInfo.mnFileId = pRefMgr->getExternalFileId(aUrl);
+ rExtInfo.maTabName = aTabName;
+ rFirstTab = rLastTab = 0;
+ }
+ return sal_True;
+}
+
+void XclImpChangeTrack::ReadFormula( ScTokenArray*& rpTokenArray, const ScAddress& rPosition )
+{
+ sal_uInt16 nFmlSize;
+ *pStrm >> nFmlSize;
+
+ // create a memory stream and copy the formula to be able to read simultaneously
+ // the formula and the additional 3D tab ref data following the formula
+ // here we have to simulate an Excel record to be able to use an XclImpStream...
+ // 2do: remove the stream member from formula converter and add it as a parameter
+ // to the Convert() routine (to prevent the construction/destruction of the
+ // converter in each formula)
+ SvMemoryStream aMemStrm;
+ aMemStrm << (sal_uInt16) 0x0001 << nFmlSize;
+ pStrm->CopyToStream( aMemStrm, nFmlSize );
+ XclImpStream aFmlaStrm( aMemStrm, GetRoot() );
+ aFmlaStrm.StartNextRecord();
+ XclImpChTrFmlConverter aFmlConv( GetRoot(), *this );
+
+ // read the formula, 3D tab refs from extended data
+ const ScTokenArray* pArray = NULL;
+ aFmlConv.Reset( rPosition );
+ BOOL bOK = (aFmlConv.Convert( pArray, aFmlaStrm, nFmlSize, false, FT_CellFormula) == ConvOK); // JEG : Check This
+ rpTokenArray = (bOK && pArray) ? new ScTokenArray( *pArray ) : NULL;
+ pStrm->Ignore( 1 );
+}
+
+void XclImpChangeTrack::ReadCell(
+ ScBaseCell*& rpCell,
+ sal_uInt32& rFormat,
+ sal_uInt16 nFlags,
+ const ScAddress& rPosition )
+{
+ rpCell = NULL;
+ rFormat = 0;
+ switch( nFlags & EXC_CHTR_TYPE_MASK )
+ {
+ case EXC_CHTR_TYPE_EMPTY:
+ break;
+ case EXC_CHTR_TYPE_RK:
+ {
+ double fValue = ReadRK();
+ if( pStrm->IsValid() )
+ rpCell = new ScValueCell( fValue );
+ }
+ break;
+ case EXC_CHTR_TYPE_DOUBLE:
+ {
+ double fValue;
+ *pStrm >> fValue;
+ if( pStrm->IsValid() )
+ rpCell = new ScValueCell( fValue );
+ }
+ break;
+ case EXC_CHTR_TYPE_STRING:
+ {
+ String sString( pStrm->ReadUniString() );
+ if( pStrm->IsValid() )
+ rpCell = new ScStringCell( sString );
+ }
+ break;
+ case EXC_CHTR_TYPE_BOOL:
+ {
+ double fValue = (double) ReadBool();
+ if( pStrm->IsValid() )
+ {
+ rpCell = new ScValueCell( fValue );
+ rFormat = GetFormatter().GetStandardFormat( NUMBERFORMAT_LOGICAL, ScGlobal::eLnge );
+ }
+ }
+ break;
+ case EXC_CHTR_TYPE_FORMULA:
+ {
+ ScTokenArray* pTokenArray = NULL;
+ ReadFormula( pTokenArray, rPosition );
+ if( pStrm->IsValid() && pTokenArray )
+ rpCell = new ScFormulaCell( GetDocPtr(), rPosition, pTokenArray );
+ }
+ break;
+ default:
+ DBG_ERROR( "XclImpChangeTrack::ReadCell - unknown data type" );
+ }
+}
+
+void XclImpChangeTrack::ReadChTrInsert()
+{
+ *pStrm >> aRecHeader;
+ if( CheckRecord( EXC_CHTR_OP_UNKNOWN ) )
+ {
+ if( (aRecHeader.nOpCode != EXC_CHTR_OP_INSROW) &&
+ (aRecHeader.nOpCode != EXC_CHTR_OP_INSCOL) &&
+ (aRecHeader.nOpCode != EXC_CHTR_OP_DELROW) &&
+ (aRecHeader.nOpCode != EXC_CHTR_OP_DELCOL) )
+ {
+ DBG_ERROR( "XclImpChangeTrack::ReadChTrInsert - unknown action" );
+ return;
+ }
+
+ ScRange aRange;
+ aRange.aStart.SetTab( ReadTabNum() );
+ aRange.aEnd.SetTab( aRange.aStart.Tab() );
+ pStrm->Ignore( 2 );
+ Read2DRange( aRange );
+
+ if( aRecHeader.nOpCode & EXC_CHTR_OP_COLFLAG )
+ aRange.aEnd.SetRow( MAXROW );
+ else
+ aRange.aEnd.SetCol( MAXCOL );
+
+ BOOL bValid = pStrm->IsValid();
+ if( FoundNestedMode() )
+ ReadNestedRecords();
+
+ if( bValid )
+ {
+ if( aRecHeader.nOpCode & EXC_CHTR_OP_DELFLAG )
+ DoDeleteRange( aRange );
+ else
+ DoInsertRange( aRange );
+ }
+ }
+}
+
+void XclImpChangeTrack::ReadChTrInfo()
+{
+ pStrm->DisableDecryption();
+ pStrm->Ignore( 32 );
+ String sUsername( pStrm->ReadUniString() );
+ if( !pStrm->IsValid() ) return;
+
+ if( sUsername.Len() )
+ pChangeTrack->SetUser( sUsername );
+ pStrm->Seek( 148 );
+ if( !pStrm->IsValid() ) return;
+
+ DateTime aDateTime;
+ ReadDateTime( aDateTime );
+ if( pStrm->IsValid() )
+ pChangeTrack->SetFixDateTimeLocal( aDateTime );
+}
+
+void XclImpChangeTrack::ReadChTrCellContent()
+{
+ *pStrm >> aRecHeader;
+ if( CheckRecord( EXC_CHTR_OP_CELL ) )
+ {
+ ScAddress aPosition;
+ SCTAB nTab = ReadTabNum();
+ aPosition.SetTab( nTab );
+ sal_uInt16 nValueType;
+ *pStrm >> nValueType;
+ sal_uInt16 nOldValueType = (nValueType >> 3) & EXC_CHTR_TYPE_MASK;
+ sal_uInt16 nNewValueType = nValueType & EXC_CHTR_TYPE_MASK;
+ pStrm->Ignore( 2 );
+ Read2DAddress( aPosition );
+ sal_uInt16 nOldSize;
+ *pStrm >> nOldSize;
+ DBG_ASSERT( (nOldSize == 0) == (nOldValueType == EXC_CHTR_TYPE_EMPTY),
+ "XclImpChangeTrack::ReadChTrCellContent - old value mismatch" );
+ pStrm->Ignore( 4 );
+ switch( nValueType & EXC_CHTR_TYPE_FORMATMASK )
+ {
+ case 0x0000: break;
+ case 0x1100: pStrm->Ignore( 16 ); break;
+ case 0x1300: pStrm->Ignore( 8 ); break;
+ default: DBG_ERROR( "XclImpChangeTrack::ReadChTrCellContent - unknown format info" );
+ }
+
+ ScBaseCell* pOldCell;
+ ScBaseCell* pNewCell;
+ sal_uInt32 nOldFormat;
+ sal_uInt32 nNewFormat;
+ ReadCell( pOldCell, nOldFormat, nOldValueType, aPosition );
+ ReadCell( pNewCell, nNewFormat, nNewValueType, aPosition );
+ if( !pStrm->IsValid() || (pStrm->GetRecLeft() > 0) )
+ {
+ DBG_ERROR( "XclImpChangeTrack::ReadChTrCellContent - bytes left, action ignored" );
+ if( pOldCell )
+ pOldCell->Delete();
+ if( pNewCell )
+ pNewCell->Delete();
+ }
+ else
+ {
+ ScChangeActionContent* pNewAction =
+ pChangeTrack->AppendContentOnTheFly( aPosition, pOldCell, pNewCell, nOldFormat, nNewFormat );
+ DoAcceptRejectAction( pNewAction );
+ }
+ }
+}
+
+void XclImpChangeTrack::ReadChTrTabId()
+{
+ if( nTabIdCount == 0 ) // read only 1st time, otherwise calculated by <ReadChTrInsertTab()>
+ nTabIdCount = static_cast< sal_uInt16 >( pStrm->GetRecLeft() >> 1 );
+}
+
+void XclImpChangeTrack::ReadChTrMoveRange()
+{
+ *pStrm >> aRecHeader;
+ if( CheckRecord( EXC_CHTR_OP_MOVE ) )
+ {
+ ScRange aSourceRange;
+ ScRange aDestRange;
+ aDestRange.aStart.SetTab( ReadTabNum() );
+ aDestRange.aEnd.SetTab( aDestRange.aStart.Tab() );
+ Read2DRange( aSourceRange );
+ Read2DRange( aDestRange );
+ aSourceRange.aStart.SetTab( ReadTabNum() );
+ aSourceRange.aEnd.SetTab( aSourceRange.aStart.Tab() );
+
+ BOOL bValid = pStrm->IsValid();
+ if( FoundNestedMode() )
+ ReadNestedRecords();
+
+ if( bValid )
+ {
+ pChangeTrack->AppendMove( aSourceRange, aDestRange, NULL );
+ DoAcceptRejectAction( pChangeTrack->GetLast() );
+ }
+ }
+}
+
+void XclImpChangeTrack::ReadChTrInsertTab()
+{
+ *pStrm >> aRecHeader;
+ if( CheckRecord( EXC_CHTR_OP_INSTAB ) )
+ {
+ SCTAB nTab = ReadTabNum();
+ if( pStrm->IsValid() )
+ {
+ nTabIdCount++;
+ DoInsertRange( ScRange( 0, 0, nTab, MAXCOL, MAXROW, nTab ) );
+ }
+ }
+}
+
+void XclImpChangeTrack::InitNestedMode()
+{
+ DBG_ASSERT( eNestedMode == nmBase, "XclImpChangeTrack::InitNestedMode - unexpected nested mode" );
+ if( eNestedMode == nmBase )
+ eNestedMode = nmFound;
+}
+
+void XclImpChangeTrack::ReadNestedRecords()
+{
+ DBG_ASSERT( eNestedMode == nmFound, "XclImpChangeTrack::StartNestedMode - missing nested mode" );
+ if( eNestedMode == nmFound )
+ {
+ eNestedMode = nmNested;
+ ReadRecords();
+ }
+}
+
+sal_Bool XclImpChangeTrack::EndNestedMode()
+{
+ DBG_ASSERT( eNestedMode != nmBase, "XclImpChangeTrack::EndNestedMode - missing nested mode" );
+ sal_Bool bReturn = (eNestedMode == nmNested);
+ eNestedMode = nmBase;
+ return bReturn;
+}
+
+void XclImpChangeTrack::ReadRecords()
+{
+ sal_Bool bExitLoop = sal_False;
+
+ while( !bExitLoop && !bGlobExit && pStrm->StartNextRecord() )
+ {
+ switch( pStrm->GetRecId() )
+ {
+ case 0x000A: bGlobExit = sal_True; break;
+ case 0x0137: ReadChTrInsert(); break;
+ case 0x0138: ReadChTrInfo(); break;
+ case 0x013B: ReadChTrCellContent(); break;
+ case 0x013D: ReadChTrTabId(); break;
+ case 0x0140: ReadChTrMoveRange(); break;
+ case 0x014D: ReadChTrInsertTab(); break;
+ case 0x014E:
+ case 0x0150: InitNestedMode(); break;
+ case 0x014F:
+ case 0x0151: bExitLoop = EndNestedMode(); break;
+ }
+ }
+}
+
+void XclImpChangeTrack::Apply()
+{
+ if( pChangeTrack )
+ {
+ pChangeTrack->SetUser( sOldUsername );
+ pChangeTrack->SetUseFixDateTime( FALSE );
+
+ GetDoc().SetChangeTrack( pChangeTrack );
+ pChangeTrack = NULL;
+
+ ScChangeViewSettings aSettings;
+ aSettings.SetShowChanges( TRUE );
+ GetDoc().SetChangeViewSettings( aSettings );
+ }
+}
+
+//___________________________________________________________________
+// class XclImpChTrFmlConverter
+
+XclImpChTrFmlConverter::~XclImpChTrFmlConverter()
+{
+}
+
+// virtual, called from ExcToSc8::Convert()
+bool XclImpChTrFmlConverter::Read3DTabReference( UINT16 /*nIxti*/, SCTAB& rFirstTab, SCTAB& rLastTab,
+ ExternalTabInfo& rExtInfo )
+{
+ return rChangeTrack.Read3DTabRefInfo( rFirstTab, rLastTab, rExtInfo );
+}
+