update dev300-m58
[ooovba.git] / sc / source / filter / xcl97 / XclImpChangeTrack.cxx
blobc20c8ac645c5100b56df9b3aad0285ac0960dd14
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: XclImpChangeTrack.cxx,v $
10 * $Revision: 1.34.48.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include "XclImpChangeTrack.hxx"
35 #include <tools/debug.hxx>
36 #include <sot/storage.hxx>
37 #include <svtools/zforlist.hxx>
38 #include "chgviset.hxx"
39 #include "cell.hxx"
40 #include "chgtrack.hxx"
41 #include "xihelper.hxx"
42 #include "xilink.hxx"
43 #include "externalrefmgr.hxx"
45 //___________________________________________________________________
46 // class XclImpChangeTrack
48 XclImpChangeTrack::XclImpChangeTrack( const XclImpRoot& rRoot, const XclImpStream& rBookStrm ) :
49 XclImpRoot( rRoot ),
50 aRecHeader(),
51 sOldUsername(),
52 pChangeTrack( NULL ),
53 pStrm( NULL ),
54 nTabIdCount( 0 ),
55 bGlobExit( sal_False ),
56 eNestedMode( nmBase )
58 // Verify that the User Names stream exists before going any further. Excel adds both
59 // "Revision Log" and "User Names" streams when Change Tracking is active but the Revision log
60 // remains if Change Tracking is turned off.
61 SotStorageStreamRef xUserStrm = OpenStream( EXC_STREAM_USERNAMES );
62 if( !xUserStrm.Is() )
63 return;
65 xInStrm = OpenStream( EXC_STREAM_REVLOG );
66 if( xInStrm.Is() )
68 xInStrm->Seek( STREAM_SEEK_TO_END );
69 ULONG nStreamLen = xInStrm->Tell();
70 if( (xInStrm->GetErrorCode() == ERRCODE_NONE) && (nStreamLen != STREAM_SEEK_TO_END) )
72 xInStrm->Seek( STREAM_SEEK_TO_BEGIN );
73 pStrm = new XclImpStream( *xInStrm, GetRoot() );
74 pStrm->CopyDecrypterFrom( rBookStrm );
75 pChangeTrack = new ScChangeTrack( GetDocPtr() );
77 sOldUsername = pChangeTrack->GetUser();
78 pChangeTrack->SetUseFixDateTime( TRUE );
80 ReadRecords();
85 XclImpChangeTrack::~XclImpChangeTrack()
87 delete pChangeTrack;
88 delete pStrm;
91 void XclImpChangeTrack::DoAcceptRejectAction( ScChangeAction* pAction )
93 if( !pAction ) return;
94 switch( aRecHeader.nAccept )
96 case EXC_CHTR_ACCEPT:
97 pChangeTrack->Accept( pAction );
98 break;
99 case EXC_CHTR_REJECT:
100 break;
104 void XclImpChangeTrack::DoAcceptRejectAction( sal_uInt32 nFirst, sal_uInt32 nLast )
106 for( sal_uInt32 nIndex = nFirst; nIndex <= nLast; nIndex++ )
107 DoAcceptRejectAction( pChangeTrack->GetAction( nIndex ) );
110 void XclImpChangeTrack::DoInsertRange( const ScRange& rRange )
112 sal_uInt32 nFirst = pChangeTrack->GetActionMax() + 1;
113 pChangeTrack->AppendInsert( rRange );
114 sal_uInt32 nLast = pChangeTrack->GetActionMax();
115 DoAcceptRejectAction( nFirst, nLast );
118 void XclImpChangeTrack::DoDeleteRange( const ScRange& rRange )
120 ULONG nFirst, nLast;
121 pChangeTrack->AppendDeleteRange( rRange, NULL, nFirst, nLast );
122 DoAcceptRejectAction( nFirst, nLast );
125 SCTAB XclImpChangeTrack::ReadTabNum()
127 return static_cast<SCTAB>(GetTabInfo().GetCurrentIndex(
128 pStrm->ReaduInt16(), nTabIdCount ));
131 void XclImpChangeTrack::ReadDateTime( DateTime& rDateTime )
133 sal_uInt16 nYear;
134 sal_uInt8 nMonth, nDay, nHour, nMin, nSec;
136 *pStrm >> nYear >> nMonth >> nDay >> nHour >> nMin >> nSec;
138 rDateTime.SetYear( nYear );
139 rDateTime.SetMonth( nMonth );
140 rDateTime.SetDay( nDay );
141 rDateTime.SetHour( nHour );
142 rDateTime.SetMin( nMin );
143 rDateTime.SetSec( nSec );
144 rDateTime.Set100Sec( 0 );
147 sal_Bool XclImpChangeTrack::CheckRecord( sal_uInt16 nOpCode )
149 if( (nOpCode != EXC_CHTR_OP_UNKNOWN) && (aRecHeader.nOpCode != nOpCode) )
151 DBG_ERROR( "XclImpChangeTrack::CheckRecord - unknown action" );
152 return sal_False;
154 return aRecHeader.nIndex != 0;
157 sal_Bool XclImpChangeTrack::Read3DTabRefInfo( SCTAB& rFirstTab, SCTAB& rLastTab, ExcelToSc8::ExternalTabInfo& rExtInfo )
159 if( LookAtuInt8() == 0x01 )
161 rExtInfo.mbExternal = false;
162 // internal ref - read tab num and return sc tab num (position in TABID list)
163 pStrm->Ignore( 3 );
164 rFirstTab = static_cast< SCTAB >( GetTabInfo().GetCurrentIndex( pStrm->ReaduInt16(), nTabIdCount ) );
165 sal_uInt8 nFillByte = pStrm->ReaduInt8();
166 rLastTab = (nFillByte == 0x00) ?
167 static_cast< SCTAB >( GetTabInfo().GetCurrentIndex( pStrm->ReaduInt16(), nTabIdCount ) ) : rFirstTab;
169 else
171 // external ref - read doc and tab name and find sc tab num
172 // - URL
173 String aEncUrl( pStrm->ReadUniString() );
174 String aUrl;
175 bool bSelf;
176 XclImpUrlHelper::DecodeUrl( aUrl, bSelf, GetRoot(), aEncUrl );
177 pStrm->Ignore( 1 );
178 // - sheet name, always separated from URL
179 String aTabName( pStrm->ReadUniString() );
180 pStrm->Ignore( 1 );
182 rExtInfo.mbExternal = true;
183 ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
184 pRefMgr->convertToAbsName(aUrl);
185 rExtInfo.mnFileId = pRefMgr->getExternalFileId(aUrl);
186 rExtInfo.maTabName = aTabName;
187 rFirstTab = rLastTab = 0;
189 return sal_True;
192 void XclImpChangeTrack::ReadFormula( ScTokenArray*& rpTokenArray, const ScAddress& rPosition )
194 sal_uInt16 nFmlSize;
195 *pStrm >> nFmlSize;
197 // create a memory stream and copy the formula to be able to read simultaneously
198 // the formula and the additional 3D tab ref data following the formula
199 // here we have to simulate an Excel record to be able to use an XclImpStream...
200 // 2do: remove the stream member from formula converter and add it as a parameter
201 // to the Convert() routine (to prevent the construction/destruction of the
202 // converter in each formula)
203 SvMemoryStream aMemStrm;
204 aMemStrm << (sal_uInt16) 0x0001 << nFmlSize;
205 pStrm->CopyToStream( aMemStrm, nFmlSize );
206 XclImpStream aFmlaStrm( aMemStrm, GetRoot() );
207 aFmlaStrm.StartNextRecord();
208 XclImpChTrFmlConverter aFmlConv( GetRoot(), *this );
210 // read the formula, 3D tab refs from extended data
211 const ScTokenArray* pArray = NULL;
212 aFmlConv.Reset( rPosition );
213 ExcelConverterBase::ConvertParam aParam;
214 aParam.mbAllowArrays = false;
215 BOOL bOK = (aFmlConv.Convert( pArray, aFmlaStrm, nFmlSize, aParam, FT_CellFormula) == ConvOK); // JEG : Check This
216 rpTokenArray = (bOK && pArray) ? new ScTokenArray( *pArray ) : NULL;
217 pStrm->Ignore( 1 );
220 void XclImpChangeTrack::ReadCell(
221 ScBaseCell*& rpCell,
222 sal_uInt32& rFormat,
223 sal_uInt16 nFlags,
224 const ScAddress& rPosition )
226 rpCell = NULL;
227 rFormat = 0;
228 switch( nFlags & EXC_CHTR_TYPE_MASK )
230 case EXC_CHTR_TYPE_EMPTY:
231 break;
232 case EXC_CHTR_TYPE_RK:
234 double fValue = ReadRK();
235 if( pStrm->IsValid() )
236 rpCell = new ScValueCell( fValue );
238 break;
239 case EXC_CHTR_TYPE_DOUBLE:
241 double fValue;
242 *pStrm >> fValue;
243 if( pStrm->IsValid() )
244 rpCell = new ScValueCell( fValue );
246 break;
247 case EXC_CHTR_TYPE_STRING:
249 String sString( pStrm->ReadUniString() );
250 if( pStrm->IsValid() )
251 rpCell = new ScStringCell( sString );
253 break;
254 case EXC_CHTR_TYPE_BOOL:
256 double fValue = (double) ReadBool();
257 if( pStrm->IsValid() )
259 rpCell = new ScValueCell( fValue );
260 rFormat = GetFormatter().GetStandardFormat( NUMBERFORMAT_LOGICAL, ScGlobal::eLnge );
263 break;
264 case EXC_CHTR_TYPE_FORMULA:
266 ScTokenArray* pTokenArray = NULL;
267 ReadFormula( pTokenArray, rPosition );
268 if( pStrm->IsValid() && pTokenArray )
269 rpCell = new ScFormulaCell( GetDocPtr(), rPosition, pTokenArray );
271 break;
272 default:
273 DBG_ERROR( "XclImpChangeTrack::ReadCell - unknown data type" );
277 void XclImpChangeTrack::ReadChTrInsert()
279 *pStrm >> aRecHeader;
280 if( CheckRecord( EXC_CHTR_OP_UNKNOWN ) )
282 if( (aRecHeader.nOpCode != EXC_CHTR_OP_INSROW) &&
283 (aRecHeader.nOpCode != EXC_CHTR_OP_INSCOL) &&
284 (aRecHeader.nOpCode != EXC_CHTR_OP_DELROW) &&
285 (aRecHeader.nOpCode != EXC_CHTR_OP_DELCOL) )
287 DBG_ERROR( "XclImpChangeTrack::ReadChTrInsert - unknown action" );
288 return;
291 ScRange aRange;
292 aRange.aStart.SetTab( ReadTabNum() );
293 aRange.aEnd.SetTab( aRange.aStart.Tab() );
294 pStrm->Ignore( 2 );
295 Read2DRange( aRange );
297 if( aRecHeader.nOpCode & EXC_CHTR_OP_COLFLAG )
298 aRange.aEnd.SetRow( MAXROW );
299 else
300 aRange.aEnd.SetCol( MAXCOL );
302 BOOL bValid = pStrm->IsValid();
303 if( FoundNestedMode() )
304 ReadNestedRecords();
306 if( bValid )
308 if( aRecHeader.nOpCode & EXC_CHTR_OP_DELFLAG )
309 DoDeleteRange( aRange );
310 else
311 DoInsertRange( aRange );
316 void XclImpChangeTrack::ReadChTrInfo()
318 pStrm->DisableDecryption();
319 pStrm->Ignore( 32 );
320 String sUsername( pStrm->ReadUniString() );
321 if( !pStrm->IsValid() ) return;
323 if( sUsername.Len() )
324 pChangeTrack->SetUser( sUsername );
325 pStrm->Seek( 148 );
326 if( !pStrm->IsValid() ) return;
328 DateTime aDateTime;
329 ReadDateTime( aDateTime );
330 if( pStrm->IsValid() )
331 pChangeTrack->SetFixDateTimeLocal( aDateTime );
334 void XclImpChangeTrack::ReadChTrCellContent()
336 *pStrm >> aRecHeader;
337 if( CheckRecord( EXC_CHTR_OP_CELL ) )
339 ScAddress aPosition;
340 SCTAB nTab = ReadTabNum();
341 aPosition.SetTab( nTab );
342 sal_uInt16 nValueType;
343 *pStrm >> nValueType;
344 sal_uInt16 nOldValueType = (nValueType >> 3) & EXC_CHTR_TYPE_MASK;
345 sal_uInt16 nNewValueType = nValueType & EXC_CHTR_TYPE_MASK;
346 pStrm->Ignore( 2 );
347 Read2DAddress( aPosition );
348 sal_uInt16 nOldSize;
349 *pStrm >> nOldSize;
350 DBG_ASSERT( (nOldSize == 0) == (nOldValueType == EXC_CHTR_TYPE_EMPTY),
351 "XclImpChangeTrack::ReadChTrCellContent - old value mismatch" );
352 pStrm->Ignore( 4 );
353 switch( nValueType & EXC_CHTR_TYPE_FORMATMASK )
355 case 0x0000: break;
356 case 0x1100: pStrm->Ignore( 16 ); break;
357 case 0x1300: pStrm->Ignore( 8 ); break;
358 default: DBG_ERROR( "XclImpChangeTrack::ReadChTrCellContent - unknown format info" );
361 ScBaseCell* pOldCell;
362 ScBaseCell* pNewCell;
363 sal_uInt32 nOldFormat;
364 sal_uInt32 nNewFormat;
365 ReadCell( pOldCell, nOldFormat, nOldValueType, aPosition );
366 ReadCell( pNewCell, nNewFormat, nNewValueType, aPosition );
367 if( !pStrm->IsValid() || (pStrm->GetRecLeft() > 0) )
369 DBG_ERROR( "XclImpChangeTrack::ReadChTrCellContent - bytes left, action ignored" );
370 if( pOldCell )
371 pOldCell->Delete();
372 if( pNewCell )
373 pNewCell->Delete();
375 else
377 ScChangeActionContent* pNewAction =
378 pChangeTrack->AppendContentOnTheFly( aPosition, pOldCell, pNewCell, nOldFormat, nNewFormat );
379 DoAcceptRejectAction( pNewAction );
384 void XclImpChangeTrack::ReadChTrTabId()
386 if( nTabIdCount == 0 ) // read only 1st time, otherwise calculated by <ReadChTrInsertTab()>
387 nTabIdCount = static_cast< sal_uInt16 >( pStrm->GetRecLeft() >> 1 );
390 void XclImpChangeTrack::ReadChTrMoveRange()
392 *pStrm >> aRecHeader;
393 if( CheckRecord( EXC_CHTR_OP_MOVE ) )
395 ScRange aSourceRange;
396 ScRange aDestRange;
397 aDestRange.aStart.SetTab( ReadTabNum() );
398 aDestRange.aEnd.SetTab( aDestRange.aStart.Tab() );
399 Read2DRange( aSourceRange );
400 Read2DRange( aDestRange );
401 aSourceRange.aStart.SetTab( ReadTabNum() );
402 aSourceRange.aEnd.SetTab( aSourceRange.aStart.Tab() );
404 BOOL bValid = pStrm->IsValid();
405 if( FoundNestedMode() )
406 ReadNestedRecords();
408 if( bValid )
410 pChangeTrack->AppendMove( aSourceRange, aDestRange, NULL );
411 DoAcceptRejectAction( pChangeTrack->GetLast() );
416 void XclImpChangeTrack::ReadChTrInsertTab()
418 *pStrm >> aRecHeader;
419 if( CheckRecord( EXC_CHTR_OP_INSTAB ) )
421 SCTAB nTab = ReadTabNum();
422 if( pStrm->IsValid() )
424 nTabIdCount++;
425 DoInsertRange( ScRange( 0, 0, nTab, MAXCOL, MAXROW, nTab ) );
430 void XclImpChangeTrack::InitNestedMode()
432 DBG_ASSERT( eNestedMode == nmBase, "XclImpChangeTrack::InitNestedMode - unexpected nested mode" );
433 if( eNestedMode == nmBase )
434 eNestedMode = nmFound;
437 void XclImpChangeTrack::ReadNestedRecords()
439 DBG_ASSERT( eNestedMode == nmFound, "XclImpChangeTrack::StartNestedMode - missing nested mode" );
440 if( eNestedMode == nmFound )
442 eNestedMode = nmNested;
443 ReadRecords();
447 sal_Bool XclImpChangeTrack::EndNestedMode()
449 DBG_ASSERT( eNestedMode != nmBase, "XclImpChangeTrack::EndNestedMode - missing nested mode" );
450 sal_Bool bReturn = (eNestedMode == nmNested);
451 eNestedMode = nmBase;
452 return bReturn;
455 void XclImpChangeTrack::ReadRecords()
457 sal_Bool bExitLoop = sal_False;
459 while( !bExitLoop && !bGlobExit && pStrm->StartNextRecord() )
461 switch( pStrm->GetRecId() )
463 case 0x000A: bGlobExit = sal_True; break;
464 case 0x0137: ReadChTrInsert(); break;
465 case 0x0138: ReadChTrInfo(); break;
466 case 0x013B: ReadChTrCellContent(); break;
467 case 0x013D: ReadChTrTabId(); break;
468 case 0x0140: ReadChTrMoveRange(); break;
469 case 0x014D: ReadChTrInsertTab(); break;
470 case 0x014E:
471 case 0x0150: InitNestedMode(); break;
472 case 0x014F:
473 case 0x0151: bExitLoop = EndNestedMode(); break;
478 void XclImpChangeTrack::Apply()
480 if( pChangeTrack )
482 pChangeTrack->SetUser( sOldUsername );
483 pChangeTrack->SetUseFixDateTime( FALSE );
485 GetDoc().SetChangeTrack( pChangeTrack );
486 pChangeTrack = NULL;
488 ScChangeViewSettings aSettings;
489 aSettings.SetShowChanges( TRUE );
490 GetDoc().SetChangeViewSettings( aSettings );
494 //___________________________________________________________________
495 // class XclImpChTrFmlConverter
497 XclImpChTrFmlConverter::~XclImpChTrFmlConverter()
501 // virtual, called from ExcToSc8::Convert()
502 bool XclImpChTrFmlConverter::Read3DTabReference( UINT16 /*nIxti*/, SCTAB& rFirstTab, SCTAB& rLastTab,
503 ExternalTabInfo& rExtInfo )
505 return rChangeTrack.Read3DTabRefInfo( rFirstTab, rLastTab, rExtInfo );