Files
libreoffice/sc/source/core/data/documen2.cxx

1257 lines
42 KiB
C++
Raw Normal View History

2000-09-18 23:16:46 +00:00
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2000-09-18 23:16:46 +00:00
*
* Copyright 2008 by Sun Microsystems, Inc.
2000-09-18 23:16:46 +00:00
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 23:16:46 +00:00
*
* $RCSfile: documen2.cxx,v $
* $Revision: 1.72.28.6 $
2000-09-18 23:16:46 +00:00
*
* This file is part of OpenOffice.org.
2000-09-18 23:16:46 +00:00
*
* 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.
2000-09-18 23:16:46 +00:00
*
* 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).
2000-09-18 23:16:46 +00:00
*
* 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.
2000-09-18 23:16:46 +00:00
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
2000-09-18 23:16:46 +00:00
// INCLUDE ---------------------------------------------------------------
#define _ZFORLIST_DECLARE_TABLE
#include "scitems.hxx"
#include <svx/eeitem.hxx>
2000-09-18 23:16:46 +00:00
#include <svx/editeng.hxx>
#include <svx/forbiddencharacterstable.hxx>
2000-09-18 23:16:46 +00:00
#include <svx/linkmgr.hxx>
#include <svx/svdpool.hxx>
#include <svx/svdobj.hxx>
2000-09-18 23:16:46 +00:00
#include <sfx2/bindings.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/printer.hxx>
#include <svtools/zforlist.hxx>
#include <svtools/zformat.hxx>
#include <vcl/virdev.hxx>
2000-10-20 08:15:16 +00:00
#include <comphelper/processfactory.hxx>
#include <svtools/PasswordHelper.hxx>
#include <tools/tenccvt.hxx>
#include <tools/list.hxx>
#include <rtl/crc.h>
2000-09-18 23:16:46 +00:00
#include "document.hxx"
#include "table.hxx"
#include "attrib.hxx"
#include "patattr.hxx"
#include "rangenam.hxx"
#include "dbcolect.hxx"
#include "pivot.hxx"
#include "docpool.hxx"
#include "stlpool.hxx"
#include "stlsheet.hxx"
#include "globstr.hrc"
#include "chartarr.hxx"
#include "chartlock.hxx"
2000-09-18 23:16:46 +00:00
#include "rechead.hxx"
#include "global.hxx"
#include "brdcst.hxx"
#include "bcaslot.hxx"
#include "adiasync.hxx"
#include "addinlis.hxx"
#include "chartlis.hxx"
#include "markdata.hxx"
#include "conditio.hxx"
#include "validat.hxx"
#include "progress.hxx"
#include "detdata.hxx"
#include "sc.hrc" // FID_DATACHANGED
#include "ddelink.hxx"
#include "chgtrack.hxx"
#include "chgviset.hxx"
#include "editutil.hxx"
#include "hints.hxx"
#include "dpobject.hxx"
#include "indexmap.hxx"
2000-11-26 14:24:00 +00:00
#include "scrdata.hxx"
#include "poolhelp.hxx"
#include "unoreflist.hxx"
#include "listenercalls.hxx"
#include "recursionhelper.hxx"
#include "lookupcache.hxx"
// pImpl because including lookupcache.hxx in document.hxx isn't wanted, and
// dtor plus helpers are convenient.
struct ScLookupCacheMapImpl
{
ScLookupCacheMap aCacheMap;
~ScLookupCacheMapImpl()
{
freeCaches();
}
void clear()
{
freeCaches();
// Zap map.
ScLookupCacheMap aTmp;
aCacheMap.swap( aTmp);
}
private:
void freeCaches()
{
for (ScLookupCacheMap::iterator it( aCacheMap.begin()); it != aCacheMap.end(); ++it)
delete (*it).second;
}
};
2000-09-18 23:16:46 +00:00
// STATIC DATA -----------------------------------------------------------
ScDocument::ScDocument( ScDocumentMode eMode,
SfxObjectShell* pDocShell ) :
2000-10-20 08:15:16 +00:00
xServiceManager( ::comphelper::getProcessServiceFactory() ),
pEditEngine( NULL ),
pNoteEngine( NULL ),
pNoteItemPool( NULL ),
2000-09-18 23:16:46 +00:00
pShell( pDocShell ),
pPrinter( NULL ),
pVirtualDevice_100th_mm( NULL ),
pDrawLayer( NULL ),
pColorTable( NULL ),
2000-09-18 23:16:46 +00:00
pCondFormList( NULL ),
pValidationList( NULL ),
pFormatExchangeList( NULL ),
pDPCollection( NULL ),
2000-09-18 23:16:46 +00:00
pLinkManager( NULL ),
pFormulaTree( NULL ),
pEOFormulaTree( NULL ),
pFormulaTrack( NULL ),
pEOFormulaTrack( NULL ),
pOtherObjects( NULL ),
pClipData( NULL ),
pDetOpList(NULL),
pChangeTrack( NULL ),
pUnoBroadcaster( NULL ),
pUnoListenerCalls( NULL ),
pUnoRefUndoList( NULL ),
pChangeViewSettings( NULL ),
pScriptTypeData( NULL ),
pCacheFieldEditEngine( NULL ),
2000-09-18 23:16:46 +00:00
pViewOptions( NULL ),
pDocOptions( NULL ),
2000-09-18 23:16:46 +00:00
pExtDocOptions( NULL ),
pConsolidateDlgData( NULL ),
pRecursionHelper( NULL ),
pAutoNameCache( NULL ),
pLookupCacheMapImpl( NULL ),
nUnoObjectId( 0 ),
nRangeOverflowType( 0 ),
2000-09-18 23:16:46 +00:00
aCurTextWidthCalcPos(MAXCOL,0,0),
nFormulaCodeInTree(0),
nXMLImportedFormulaCount( 0 ),
nInterpretLevel(0),
nMacroInterpretLevel(0),
nInterpreterTableOpLevel(0),
nMaxTableNumber( 0 ),
nSrcVer( SC_CURRENT_VERSION ),
nSrcMaxRow( MAXROW ),
nFormulaTrackCount(0),
nHardRecalcState(0),
nVisibleTab( 0 ),
eLinkMode(LM_UNKNOWN),
bProtected( FALSE ),
bAutoCalc( eMode == SCDOCMODE_DOCUMENT ),
bAutoCalcShellDisabled( FALSE ),
bForcedFormulaPending( FALSE ),
bCalculatingFormulaTree( FALSE ),
bIsClip( eMode == SCDOCMODE_CLIP ),
bCutMode( FALSE ),
bIsUndo( eMode == SCDOCMODE_UNDO ),
bIsVisible( FALSE ),
bIsEmbedded( FALSE ),
2000-09-18 23:16:46 +00:00
// bNoSetDirty( TRUE ),
bNoSetDirty( FALSE ),
bInsertingFromOtherDoc( FALSE ),
bImportingXML( FALSE ),
bXMLFromWrapper( FALSE ),
2000-09-18 23:16:46 +00:00
bCalcingAfterLoad( FALSE ),
bNoListening( FALSE ),
bLoadingDone( TRUE ),
bIdleDisabled( FALSE ),
bInLinkUpdate( FALSE ),
bChartListenerCollectionNeedsUpdate( FALSE ),
bHasForcedFormulas( FALSE ),
bInDtorClear( FALSE ),
bExpandRefs( FALSE ),
bDetectiveDirty( FALSE ),
nMacroCallMode( SC_MACROCALL_ALLOWED ),
bHasMacroFunc( FALSE ),
nVisSpellState( 0 ),
nAsianCompression(SC_ASIANCOMPRESSION_INVALID),
nAsianKerning(SC_ASIANKERNING_INVALID),
bSetDrawDefaults( FALSE ),
2001-11-26 08:28:27 +00:00
bPastingDrawFromOtherDoc( FALSE ),
nInDdeLinkUpdate( 0 ),
bInUnoBroadcast( FALSE ),
bInUnoListenerCall( FALSE ),
eGrammar( ScGrammar::GRAM_NATIVE ),
bStyleSheetUsageInvalid( TRUE ),
bUndoEnabled( TRUE ),
mbAdjustHeightEnabled( true ),
mbExecuteLinkEnabled( true ),
mbChangeReadOnlyEnabled( false ),
mnNamedRangesLockCount( 0 )
2000-09-18 23:16:46 +00:00
{
SetStorageGrammar( ScGrammar::GRAM_STORAGE_DEFAULT);
2000-09-18 23:16:46 +00:00
eSrcSet = gsl_getSystemTextEncoding();
if ( eMode == SCDOCMODE_DOCUMENT )
{
if ( pDocShell )
pLinkManager = new SvxLinkManager( pDocShell );
xPoolHelper = new ScPoolHelper( this );
2000-09-18 23:16:46 +00:00
pTab[0] = NULL;
pBASM = new ScBroadcastAreaSlotMachine( this );
pChartListenerCollection = new ScChartListenerCollection( this );
pRefreshTimerControl = new ScRefreshTimerControl;
2000-09-18 23:16:46 +00:00
}
else
{
pTab[0] = NULL;
pBASM = NULL;
pChartListenerCollection = NULL;
pRefreshTimerControl = NULL;
2000-09-18 23:16:46 +00:00
}
for (SCTAB i=1; i<=MAXTAB; i++)
2000-09-18 23:16:46 +00:00
pTab[i] = NULL;
pRangeName = new ScRangeName( 4, 4, FALSE, this );
pDBCollection = new ScDBCollection( 4, 4, FALSE, this );
#if OLD_PIVOT_IMPLEMENTATION
2000-09-18 23:16:46 +00:00
pPivotCollection = new ScPivotCollection(4, 4, this );
#endif
2000-09-18 23:16:46 +00:00
pSelectionAttr = NULL;
pChartCollection = new ScChartCollection;
apTemporaryChartLock = std::auto_ptr< ScTemporaryChartLock >( new ScTemporaryChartLock(this) );
2000-09-18 23:16:46 +00:00
xColNameRanges = new ScRangePairList;
xRowNameRanges = new ScRangePairList;
ImplCreateOptions();
2000-11-26 12:41:18 +00:00
// languages for a visible document are set by docshell later (from options)
SetLanguage( ScGlobal::eLnge, ScGlobal::eLnge, ScGlobal::eLnge );
2000-09-18 23:16:46 +00:00
aTrackTimer.SetTimeoutHdl( LINK( this, ScDocument, TrackTimeHdl ) );
aTrackTimer.SetTimeout( 100 );
}
void ScDocument::SetStorageGrammar( ScGrammar::Grammar eGram )
{
DBG_ASSERT(
eGram == ScGrammar::GRAM_ODFF ||
eGram == ScGrammar::GRAM_PODF,
"ScDocument::SetStorageGrammar: wrong storage grammar");
eStorageGrammar = eGram;
// FIXME: the XML import shouldn't strip brackets, the compiler should
// digest them instead, which could also speedup reference recognition
// during import.
eXmlImportGrammar = ScGrammar::mergeToGrammar( eGram,
ScAddress::CONV_OOO);
}
void ScDocument::SetDocVisible( BOOL bSet )
{
// called from view ctor - only for a visible document,
// each new sheet's RTL flag is initialized from the locale
bIsVisible = bSet;
}
sal_uInt32 ScDocument::GetDocumentID() const
{
const ScDocument* pThis = this;
sal_uInt32 nCrc = rtl_crc32( 0, &pThis, sizeof(ScDocument*) );
// the this pointer only might not be sufficient
nCrc = rtl_crc32( nCrc, &pShell, sizeof(SfxObjectShell*) );
return nCrc;
}
2000-09-18 23:16:46 +00:00
void ScDocument::StartChangeTracking()
{
if (!pChangeTrack)
pChangeTrack = new ScChangeTrack( this );
}
void ScDocument::EndChangeTracking()
{
delete pChangeTrack;
pChangeTrack = NULL;
}
2000-11-21 09:24:41 +00:00
void ScDocument::SetChangeTrack( ScChangeTrack* pTrack )
{
DBG_ASSERT( pTrack->GetDocument() == this, "SetChangeTrack: different documents" );
if ( !pTrack || pTrack == pChangeTrack || pTrack->GetDocument() != this )
return ;
EndChangeTracking();
pChangeTrack = pTrack;
}
IMPL_LINK( ScDocument, TrackTimeHdl, Timer*, EMPTYARG )
2000-09-18 23:16:46 +00:00
{
if ( ScDdeLink::IsInUpdate() ) // nicht verschachteln
{
aTrackTimer.Start(); // spaeter nochmal versuchen
}
else if (pShell) // ausfuehren
{
TrackFormulas();
pShell->Broadcast( SfxSimpleHint( FID_DATACHANGED ) );
ResetChanged( ScRange(0,0,0,MAXCOL,MAXROW,MAXTAB) );
// modified...
if (!pShell->IsModified())
{
pShell->SetModified( TRUE );
2000-09-22 17:57:10 +00:00
SfxBindings* pBindings = GetViewBindings();
if (pBindings)
{
pBindings->Invalidate( SID_SAVEDOC );
pBindings->Invalidate( SID_DOC_MODIFIED );
}
2000-09-18 23:16:46 +00:00
}
}
return 0;
}
void ScDocument::StartTrackTimer()
{
if (!aTrackTimer.IsActive()) // nicht ewig aufschieben
aTrackTimer.Start();
}
ScDocument::~ScDocument()
{
DBG_ASSERT( !bInLinkUpdate, "bInLinkUpdate in dtor" );
bInDtorClear = TRUE;
// first of all disable all refresh timers by deleting the control
if ( pRefreshTimerControl )
{ // To be sure there isn't anything running do it with a protector,
// this ensures also that nothing needs the control anymore.
ScRefreshTimerProtector aProt( GetRefreshTimerControlAddress() );
delete pRefreshTimerControl, pRefreshTimerControl = NULL;
}
2000-09-18 23:16:46 +00:00
// Links aufrauemen
if ( pLinkManager )
{
// BaseLinks freigeben
for ( USHORT n = pLinkManager->GetServers().Count(); n; )
2001-04-11 13:36:34 +00:00
pLinkManager->GetServers()[ --n ]->Closed();
2000-09-18 23:16:46 +00:00
if ( pLinkManager->GetLinks().Count() )
pLinkManager->Remove( 0, pLinkManager->GetLinks().Count() );
}
ScAddInAsync::RemoveDocument( this );
ScAddInListener::RemoveDocument( this );
delete pChartListenerCollection; // vor pBASM wg. evtl. Listener!
pChartListenerCollection = NULL;
DELETEZ( pLookupCacheMapImpl); // before pBASM because of listeners
2000-09-18 23:16:46 +00:00
// BroadcastAreas vor allen Zellen zerstoeren um unnoetige
// Einzel-EndListenings der Formelzellen zu vermeiden
delete pBASM; // BroadcastAreaSlotMachine
pBASM = NULL;
if (pUnoBroadcaster)
{
delete pUnoBroadcaster; // broadcasted nochmal SFX_HINT_DYING
pUnoBroadcaster = NULL;
}
delete pUnoRefUndoList;
delete pUnoListenerCalls;
Clear( sal_True ); // TRUE = from destructor (needed for SdrModel::ClearModel)
2000-09-18 23:16:46 +00:00
if (pCondFormList)
{
pCondFormList->DeleteAndDestroy( 0, pCondFormList->Count() );
DELETEZ(pCondFormList);
}
if (pValidationList)
{
pValidationList->DeleteAndDestroy( 0, pValidationList->Count() );
DELETEZ(pValidationList);
}
delete pRangeName;
delete pDBCollection;
#if OLD_PIVOT_IMPLEMENTATION
2000-09-18 23:16:46 +00:00
delete pPivotCollection;
#endif
2000-09-18 23:16:46 +00:00
delete pSelectionAttr;
apTemporaryChartLock.reset();
2000-09-18 23:16:46 +00:00
delete pChartCollection;
DeleteDrawLayer();
delete pFormatExchangeList;
delete pPrinter;
ImplDeleteOptions();
delete pConsolidateDlgData;
delete pLinkManager;
delete pClipData;
delete pDetOpList; // loescht auch die Eintraege
delete pChangeTrack;
delete pEditEngine;
delete pNoteEngine;
delete pNoteItemPool;
2000-09-18 23:16:46 +00:00
delete pChangeViewSettings; // und weg damit
delete pVirtualDevice_100th_mm;
2000-09-18 23:16:46 +00:00
delete pDPCollection;
// delete the EditEngine before destroying the xPoolHelper
delete pCacheFieldEditEngine;
if ( xPoolHelper.isValid() && !bIsClip )
xPoolHelper->SourceDocumentGone();
xPoolHelper.unbind();
2000-09-18 23:16:46 +00:00
DeleteColorTable();
2000-11-26 14:24:00 +00:00
delete pScriptTypeData;
delete pOtherObjects;
delete pRecursionHelper;
2001-11-26 08:28:27 +00:00
DBG_ASSERT( !pAutoNameCache, "AutoNameCache still set in dtor" );
2000-09-18 23:16:46 +00:00
}
void ScDocument::InitClipPtrs( ScDocument* pSourceDoc )
{
DBG_ASSERT(bIsClip, "InitClipPtrs und nicht bIsClip");
if (pCondFormList)
{
pCondFormList->DeleteAndDestroy( 0, pCondFormList->Count() );
DELETEZ(pCondFormList);
}
if (pValidationList)
{
pValidationList->DeleteAndDestroy( 0, pValidationList->Count() );
DELETEZ(pValidationList);
}
Clear();
xPoolHelper = pSourceDoc->xPoolHelper;
2000-09-18 23:16:46 +00:00
// bedingte Formate / Gueltigkeiten
//! Vorlagen kopieren?
const ScConditionalFormatList* pSourceCond = pSourceDoc->pCondFormList;
if ( pSourceCond )
pCondFormList = new ScConditionalFormatList(this, *pSourceCond);
const ScValidationDataList* pSourceValid = pSourceDoc->pValidationList;
if ( pSourceValid )
pValidationList = new ScValidationDataList(this, *pSourceValid);
// Links in Stream speichern
delete pClipData;
if (pSourceDoc->HasDdeLinks())
{
pClipData = new SvMemoryStream;
pSourceDoc->SaveDdeLinks(*pClipData);
}
else
pClipData = NULL;
// Options pointers exist (ImplCreateOptions) for any document.
// Must be copied for correct results in OLE objects (#i42666#).
SetDocOptions( pSourceDoc->GetDocOptions() );
SetViewOptions( pSourceDoc->GetViewOptions() );
2000-09-18 23:16:46 +00:00
}
SvNumberFormatter* ScDocument::GetFormatTable() const
{
return xPoolHelper->GetFormTable();
}
SfxItemPool* ScDocument::GetEditPool() const
{
return xPoolHelper->GetEditPool();
}
SfxItemPool* ScDocument::GetEnginePool() const
{
return xPoolHelper->GetEnginePool();
}
2000-09-18 23:16:46 +00:00
ScFieldEditEngine& ScDocument::GetEditEngine()
{
if ( !pEditEngine )
{
pEditEngine = new ScFieldEditEngine( GetEnginePool(), GetEditPool() );
2000-09-18 23:16:46 +00:00
pEditEngine->SetUpdateMode( FALSE );
pEditEngine->EnableUndo( FALSE );
pEditEngine->SetRefMapMode( MAP_100TH_MM );
pEditEngine->SetForbiddenCharsTable( xForbiddenCharacters );
2000-09-18 23:16:46 +00:00
}
return *pEditEngine;
}
ScNoteEditEngine& ScDocument::GetNoteEngine()
{
if ( !pNoteEngine )
{
pNoteEngine = new ScNoteEditEngine( GetEnginePool(), GetEditPool() );
pNoteEngine->SetUpdateMode( FALSE );
pNoteEngine->EnableUndo( FALSE );
pNoteEngine->SetRefMapMode( MAP_100TH_MM );
pNoteEngine->SetForbiddenCharsTable( xForbiddenCharacters );
const SfxItemSet& rItemSet = GetDefPattern()->GetItemSet();
SfxItemSet* pEEItemSet = new SfxItemSet( pNoteEngine->GetEmptyItemSet() );
ScPatternAttr::FillToEditItemSet( *pEEItemSet, rItemSet );
pNoteEngine->SetDefaults( pEEItemSet ); // edit engine takes ownership
}
return *pNoteEngine;
}
SfxItemPool& ScDocument::GetNoteItemPool()
{
if ( !pNoteItemPool )
pNoteItemPool = new SfxItemPool(SdrObject::GetGlobalDrawObjectItemPool());
return *pNoteItemPool;
}
2000-09-18 23:16:46 +00:00
void ScDocument::ResetClip( ScDocument* pSourceDoc, const ScMarkData* pMarks )
{
if (bIsClip)
{
InitClipPtrs(pSourceDoc);
for (SCTAB i = 0; i <= MAXTAB; i++)
2000-09-18 23:16:46 +00:00
if (pSourceDoc->pTab[i])
if (!pMarks || pMarks->GetTableSelect(i))
{
String aString;
pSourceDoc->pTab[i]->GetName(aString);
pTab[i] = new ScTable(this, i, aString);
pTab[i]->SetLayoutRTL( pSourceDoc->pTab[i]->IsLayoutRTL() );
2000-09-18 23:16:46 +00:00
nMaxTableNumber = i+1;
}
}
else
{
2000-09-18 23:16:46 +00:00
DBG_ERROR("ResetClip");
}
2000-09-18 23:16:46 +00:00
}
void ScDocument::ResetClip( ScDocument* pSourceDoc, SCTAB nTab )
2000-09-18 23:16:46 +00:00
{
if (bIsClip)
{
InitClipPtrs(pSourceDoc);
pTab[nTab] = new ScTable(this, nTab,
String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("baeh")));
if (pSourceDoc->pTab[nTab])
pTab[nTab]->SetLayoutRTL( pSourceDoc->pTab[nTab]->IsLayoutRTL() );
2000-09-18 23:16:46 +00:00
nMaxTableNumber = nTab+1;
}
else
{
2000-09-18 23:16:46 +00:00
DBG_ERROR("ResetClip");
}
2000-09-18 23:16:46 +00:00
}
void ScDocument::DeleteNumberFormat( const sal_uInt32* /* pDelKeys */, sal_uInt32 /* nCount */ )
2000-09-18 23:16:46 +00:00
{
/*
for (ULONG i = 0; i < nCount; i++)
xPoolHelper->GetFormTable()->DeleteEntry(pDelKeys[i]);
2000-09-18 23:16:46 +00:00
*/
}
void ScDocument::PutCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
2000-09-18 23:16:46 +00:00
ScBaseCell* pCell, ULONG nFormatIndex, BOOL bForceTab )
{
if (VALIDTAB(nTab))
{
if ( bForceTab && !pTab[nTab] )
{
BOOL bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
pTab[nTab] = new ScTable(this, nTab,
String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
bExtras, bExtras);
}
if (pTab[nTab])
pTab[nTab]->PutCell( nCol, nRow, nFormatIndex, pCell );
}
}
void ScDocument::PutCell( const ScAddress& rPos, ScBaseCell* pCell,
ULONG nFormatIndex, BOOL bForceTab )
{
SCTAB nTab = rPos.Tab();
2000-09-18 23:16:46 +00:00
if ( bForceTab && !pTab[nTab] )
{
BOOL bExtras = !bIsUndo; // Spaltenbreiten, Zeilenhoehen, Flags
pTab[nTab] = new ScTable(this, nTab,
String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("temp")),
bExtras, bExtras);
}
if (pTab[nTab])
pTab[nTab]->PutCell( rPos, nFormatIndex, pCell );
}
BOOL ScDocument::GetPrintArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow,
2000-09-18 23:16:46 +00:00
BOOL bNotes ) const
{
if (ValidTab(nTab) && pTab[nTab])
2000-09-18 23:16:46 +00:00
{
BOOL bAny = pTab[nTab]->GetPrintArea( rEndCol, rEndRow, bNotes );
if (pDrawLayer)
{
ScRange aDrawRange(0,0,nTab, MAXCOL,MAXROW,nTab);
if (DrawGetPrintArea( aDrawRange, TRUE, TRUE ))
{
if (aDrawRange.aEnd.Col()>rEndCol) rEndCol=aDrawRange.aEnd.Col();
if (aDrawRange.aEnd.Row()>rEndRow) rEndRow=aDrawRange.aEnd.Row();
bAny = TRUE;
}
}
return bAny;
}
rEndCol = 0;
rEndRow = 0;
return FALSE;
}
BOOL ScDocument::GetPrintAreaHor( SCTAB nTab, SCROW nStartRow, SCROW nEndRow,
SCCOL& rEndCol, BOOL bNotes ) const
2000-09-18 23:16:46 +00:00
{
if (ValidTab(nTab) && pTab[nTab])
2000-09-18 23:16:46 +00:00
{
BOOL bAny = pTab[nTab]->GetPrintAreaHor( nStartRow, nEndRow, rEndCol, bNotes );
if (pDrawLayer)
{
ScRange aDrawRange(0,nStartRow,nTab, MAXCOL,nEndRow,nTab);
if (DrawGetPrintArea( aDrawRange, TRUE, FALSE ))
{
if (aDrawRange.aEnd.Col()>rEndCol) rEndCol=aDrawRange.aEnd.Col();
bAny = TRUE;
}
}
return bAny;
}
rEndCol = 0;
return FALSE;
}
BOOL ScDocument::GetPrintAreaVer( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol,
SCROW& rEndRow, BOOL bNotes ) const
2000-09-18 23:16:46 +00:00
{
if (ValidTab(nTab) && pTab[nTab])
2000-09-18 23:16:46 +00:00
{
BOOL bAny = pTab[nTab]->GetPrintAreaVer( nStartCol, nEndCol, rEndRow, bNotes );
if (pDrawLayer)
{
ScRange aDrawRange(nStartCol,0,nTab, nEndCol,MAXROW,nTab);
if (DrawGetPrintArea( aDrawRange, FALSE, TRUE ))
{
if (aDrawRange.aEnd.Row()>rEndRow) rEndRow=aDrawRange.aEnd.Row();
bAny = TRUE;
}
}
return bAny;
}
rEndRow = 0;
return FALSE;
}
BOOL ScDocument::GetDataStart( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow ) const
2000-09-18 23:16:46 +00:00
{
if (ValidTab(nTab) && pTab[nTab])
2000-09-18 23:16:46 +00:00
{
BOOL bAny = pTab[nTab]->GetDataStart( rStartCol, rStartRow );
if (pDrawLayer)
{
ScRange aDrawRange(0,0,nTab, MAXCOL,MAXROW,nTab);
if (DrawGetPrintArea( aDrawRange, TRUE, TRUE ))
{
if (aDrawRange.aStart.Col()<rStartCol) rStartCol=aDrawRange.aStart.Col();
if (aDrawRange.aStart.Row()<rStartRow) rStartRow=aDrawRange.aStart.Row();
bAny = TRUE;
}
}
return bAny;
}
rStartCol = 0;
rStartRow = 0;
return FALSE;
}
BOOL ScDocument::MoveTab( SCTAB nOldPos, SCTAB nNewPos )
2000-09-18 23:16:46 +00:00
{
if (nOldPos == nNewPos) return FALSE;
BOOL bValid = FALSE;
if (VALIDTAB(nOldPos))
{
if (pTab[nOldPos])
{
SCTAB nTabCount = GetTableCount();
2000-09-18 23:16:46 +00:00
if (nTabCount > 1)
{
BOOL bOldAutoCalc = GetAutoCalc();
SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
SetNoListening( TRUE );
ScProgress* pProgress = new ScProgress( GetDocumentShell(),
ScGlobal::GetRscString(STR_UNDO_MOVE_TAB), GetCodeCount() );
if (nNewPos == SC_TAB_APPEND)
nNewPos = nTabCount-1;
// Referenz-Updaterei
//! mit UpdateReference zusammenfassen!
SCsTAB nDz = ((SCsTAB)nNewPos) - (SCsTAB)nOldPos;
2000-09-18 23:16:46 +00:00
ScRange aSourceRange( 0,0,nOldPos, MAXCOL,MAXROW,nOldPos );
pRangeName->UpdateTabRef(nOldPos, 3, nNewPos);
pDBCollection->UpdateMoveTab( nOldPos, nNewPos );
xColNameRanges->UpdateReference( URM_REORDER, this, aSourceRange, 0,0,nDz );
xRowNameRanges->UpdateReference( URM_REORDER, this, aSourceRange, 0,0,nDz );
#if OLD_PIVOT_IMPLEMENTATION
2000-09-18 23:16:46 +00:00
if (pPivotCollection)
pPivotCollection->UpdateReference( URM_REORDER,
0,0,nOldPos, MAXCOL,MAXROW,nOldPos, 0,0,nDz );
#endif
2000-09-18 23:16:46 +00:00
if (pDPCollection)
pDPCollection->UpdateReference( URM_REORDER, aSourceRange, 0,0,nDz );
if (pDetOpList)
pDetOpList->UpdateReference( this, URM_REORDER, aSourceRange, 0,0,nDz );
UpdateChartRef( URM_REORDER,
0,0,nOldPos, MAXCOL,MAXROW,nOldPos, 0,0,nDz );
2000-10-30 10:33:41 +00:00
UpdateRefAreaLinks( URM_REORDER, aSourceRange, 0,0,nDz );
2000-09-18 23:16:46 +00:00
if ( pCondFormList )
pCondFormList->UpdateMoveTab( nOldPos, nNewPos );
if ( pValidationList )
pValidationList->UpdateMoveTab( nOldPos, nNewPos );
2000-09-18 23:16:46 +00:00
if ( pUnoBroadcaster )
pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_REORDER,
aSourceRange, 0,0,nDz ) );
ScTable* pSaveTab = pTab[nOldPos];
SCTAB i;
2000-09-18 23:16:46 +00:00
for (i = nOldPos + 1; i < nTabCount; i++)
pTab[i - 1] = pTab[i];
pTab[i-1] = NULL;
for (i = nTabCount - 1; i > nNewPos; i--)
pTab[i] = pTab[i - 1];
pTab[nNewPos] = pSaveTab;
for (i = 0; i <= MAXTAB; i++)
if (pTab[i])
pTab[i]->UpdateMoveTab( nOldPos, nNewPos, i, *pProgress );
delete pProgress; // freimachen fuer evtl. andere
for (i = 0; i <= MAXTAB; i++)
if (pTab[i])
pTab[i]->UpdateCompile();
SetNoListening( FALSE );
for (i = 0; i <= MAXTAB; i++)
if (pTab[i])
pTab[i]->StartAllListeners();
2000-12-13 11:43:43 +00:00
// #81844# sheet names of references may not be valid until sheet is moved
pChartListenerCollection->UpdateScheduledSeriesRanges();
2000-09-18 23:16:46 +00:00
SetDirty();
SetAutoCalc( bOldAutoCalc );
if (pDrawLayer)
DrawMovePage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
2000-09-18 23:16:46 +00:00
bValid = TRUE;
}
}
}
return bValid;
}
BOOL ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyMarked )
2000-09-18 23:16:46 +00:00
{
if (SC_TAB_APPEND == nNewPos ) nNewPos = nMaxTableNumber;
String aName;
GetName(nOldPos, aName);
// vorneweg testen, ob der Prefix als gueltig erkannt wird
// wenn nicht, nur doppelte vermeiden
BOOL bPrefix = ValidTabName( aName );
DBG_ASSERT(bPrefix, "ungueltiger Tabellenname");
SCTAB nDummy;
2000-09-18 23:16:46 +00:00
CreateValidTabName(aName);
BOOL bValid;
if (bPrefix)
bValid = ( ValidNewTabName(aName) && (nMaxTableNumber <= MAXTAB) );
else
bValid = ( !GetTable( aName, nDummy ) && (nMaxTableNumber <= MAXTAB) );
BOOL bOldAutoCalc = GetAutoCalc();
SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
if (bValid)
{
if (nNewPos == nMaxTableNumber)
{
pTab[nMaxTableNumber] = new ScTable(this, nMaxTableNumber, aName);
++nMaxTableNumber;
}
else
{
if (VALIDTAB(nNewPos) && (nNewPos < nMaxTableNumber))
{
SetNoListening( TRUE );
ScRange aRange( 0,0,nNewPos, MAXCOL,MAXROW,MAXTAB );
xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
pRangeName->UpdateTabRef(nNewPos, 1);
pDBCollection->UpdateReference(
URM_INSDEL, 0,0,nNewPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
#if OLD_PIVOT_IMPLEMENTATION
2000-09-18 23:16:46 +00:00
if (pPivotCollection)
pPivotCollection->UpdateReference(
URM_INSDEL, 0,0,nNewPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
#endif
2000-09-18 23:16:46 +00:00
if (pDPCollection)
pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
if (pDetOpList)
pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,1 );
UpdateChartRef( URM_INSDEL, 0,0,nNewPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
2000-10-30 10:33:41 +00:00
UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,1 );
2000-09-18 23:16:46 +00:00
if ( pUnoBroadcaster )
pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,1 ) );
SCTAB i;
2000-09-18 23:16:46 +00:00
for (i = 0; i <= MAXTAB; i++)
if (pTab[i] && i != nOldPos)
pTab[i]->UpdateInsertTab(nNewPos);
for (i = nMaxTableNumber; i > nNewPos; i--)
pTab[i] = pTab[i - 1];
if (nNewPos <= nOldPos)
nOldPos++;
pTab[nNewPos] = new ScTable(this, nNewPos, aName);
++nMaxTableNumber;
bValid = TRUE;
for (i = 0; i <= MAXTAB; i++)
if (pTab[i] && i != nOldPos && i != nNewPos)
pTab[i]->UpdateCompile();
SetNoListening( FALSE );
for (i = 0; i <= MAXTAB; i++)
if (pTab[i] && i != nOldPos && i != nNewPos)
pTab[i]->StartAllListeners();
// update conditional formats after table is inserted
if ( pCondFormList )
pCondFormList->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
if ( pValidationList )
pValidationList->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
2000-12-13 11:43:43 +00:00
// #81844# sheet names of references may not be valid until sheet is copied
pChartListenerCollection->UpdateScheduledSeriesRanges();
2000-09-18 23:16:46 +00:00
}
else
bValid = FALSE;
}
}
if (bValid)
{
SetNoListening( TRUE ); // noch nicht bei CopyToTable/Insert
pTab[nOldPos]->CopyToTable(0, 0, MAXCOL, MAXROW, IDF_ALL, (pOnlyMarked != NULL),
pTab[nNewPos], pOnlyMarked );
SCsTAB nDz;
2000-09-18 23:16:46 +00:00
/* if (nNewPos < nOldPos)
nDz = ((short)nNewPos) - (short)nOldPos + 1;
else
*/ nDz = ((short)nNewPos) - (short)nOldPos;
pTab[nNewPos]->UpdateReference(URM_COPY, 0, 0, nNewPos , MAXCOL, MAXROW,
nNewPos, 0, 0, nDz, NULL);
pTab[nNewPos]->UpdateInsertTabAbs(nNewPos); // alle abs. um eins hoch!!
pTab[nOldPos]->UpdateInsertTab(nNewPos);
pTab[nOldPos]->UpdateCompile();
pTab[nNewPos]->UpdateCompile( TRUE ); // #67996# maybe already compiled in Clone, but used names need recompilation
SetNoListening( FALSE );
pTab[nOldPos]->StartAllListeners();
pTab[nNewPos]->StartAllListeners();
SetDirty();
SetAutoCalc( bOldAutoCalc );
if (pDrawLayer)
DrawCopyPage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
2000-09-18 23:16:46 +00:00
pTab[nNewPos]->SetPageStyle( pTab[nOldPos]->GetPageStyle() );
}
else
SetAutoCalc( bOldAutoCalc );
return bValid;
}
ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
SCTAB nDestPos, BOOL bInsertNew,
2000-09-18 23:16:46 +00:00
BOOL bResultsOnly )
{
ULONG nRetVal = 1; // 0 => Fehler 1 = ok
// 2 => RefBox, 3 => NameBox
// 4 => beides
BOOL bValid = TRUE;
if (bInsertNew) // neu einfuegen
{
String aName;
pSrcDoc->GetName(nSrcPos, aName);
CreateValidTabName(aName);
bValid = InsertTab(nDestPos, aName);
}
else // bestehende Tabelle ersetzen
{
if (VALIDTAB(nDestPos) && pTab[nDestPos])
{
pTab[nDestPos]->DeleteArea( 0,0, MAXCOL,MAXROW, IDF_ALL );
}
else
bValid = FALSE;
}
if (bValid)
{
BOOL bOldAutoCalcSrc = FALSE;
2000-09-18 23:16:46 +00:00
BOOL bOldAutoCalc = GetAutoCalc();
SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
SetNoListening( TRUE );
if ( bResultsOnly )
{
bOldAutoCalcSrc = pSrcDoc->GetAutoCalc();
pSrcDoc->SetAutoCalc( TRUE ); // falls was berechnet werden muss
}
SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
if (pOtherFormatter && pOtherFormatter != pThisFormatter)
2000-09-18 23:16:46 +00:00
{
SvNumberFormatterIndexTable* pExchangeList =
pThisFormatter->MergeFormatter(*(pOtherFormatter));
2000-09-18 23:16:46 +00:00
if (pExchangeList->Count() > 0)
pFormatExchangeList = pExchangeList;
}
nDestPos = Min(nDestPos, (SCTAB)(GetTableCount() - 1));
{ // scope for bulk broadcast
ScBulkBroadcast aBulkBroadcast( pBASM);
pSrcDoc->pTab[nSrcPos]->CopyToTable(0, 0, MAXCOL, MAXROW,
( bResultsOnly ? IDF_ALL & ~IDF_FORMULA : IDF_ALL),
FALSE, pTab[nDestPos] );
}
2000-09-18 23:16:46 +00:00
pFormatExchangeList = NULL;
pTab[nDestPos]->SetTabNo(nDestPos);
if ( !bResultsOnly )
{
BOOL bNamesLost = FALSE;
2000-09-18 23:16:46 +00:00
USHORT nSrcRangeNames = pSrcDoc->pRangeName->GetCount();
// array containing range names which might need update of indices
ScRangeData** pSrcRangeNames = nSrcRangeNames ? new ScRangeData* [nSrcRangeNames] : NULL;
// the index mapping thereof
ScIndexMap aSrcRangeMap( nSrcRangeNames );
BOOL bRangeNameReplace = FALSE;
// find named ranges that are used in the source sheet
std::set<USHORT> aUsedNames;
pSrcDoc->pTab[nSrcPos]->FindRangeNamesInUse( 0, 0, MAXCOL, MAXROW, aUsedNames );
2000-09-18 23:16:46 +00:00
for (USHORT i = 0; i < nSrcRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch !!!
{
ScRangeData* pSrcData = (*pSrcDoc->pRangeName)[i];
USHORT nOldIndex = pSrcData->GetIndex();
bool bInUse = ( aUsedNames.find(nOldIndex) != aUsedNames.end() );
2000-09-18 23:16:46 +00:00
if (bInUse)
{
USHORT nExisting = 0;
if ( pRangeName->SearchName( pSrcData->GetName(), nExisting ) )
2000-09-18 23:16:46 +00:00
{
// the name exists already in the destination document
// -> use the existing name, but show a warning
// (when refreshing links, the existing name is used and the warning not shown)
ScRangeData* pExistingData = (*pRangeName)[nExisting];
USHORT nExistingIndex = pExistingData->GetIndex();
pSrcRangeNames[i] = NULL; // don't modify the named range
aSrcRangeMap.SetPair( i, nOldIndex, nExistingIndex );
2000-09-18 23:16:46 +00:00
bRangeNameReplace = TRUE;
bNamesLost = TRUE;
2000-09-18 23:16:46 +00:00
}
else
{
ScRangeData* pData = new ScRangeData( *pSrcData );
pData->SetDocument(this);
if ( pRangeName->FindIndex( pData->GetIndex() ) )
pData->SetIndex(0); // need new index, done in Insert
if (!pRangeName->Insert(pData))
{
DBG_ERROR("can't insert name"); // shouldn't happen
delete pData;
}
else
{
pData->TransferTabRef( nSrcPos, nDestPos );
pSrcRangeNames[i] = pData;
USHORT nNewIndex = pData->GetIndex();
aSrcRangeMap.SetPair( i, nOldIndex, nNewIndex );
if ( !bRangeNameReplace )
bRangeNameReplace = ( nOldIndex != nNewIndex );
}
2000-09-18 23:16:46 +00:00
}
}
else
{
pSrcRangeNames[i] = NULL;
//aSrcRangeMap.SetPair( i, 0, 0 ); // not needed, defaulted
}
}
if ( bRangeNameReplace )
{
// first update all inserted named formulas if they contain other
// range names and used indices changed
for (USHORT i = 0; i < nSrcRangeNames; i++) //! DB-Bereiche Pivot-Bereiche auch
{
if ( pSrcRangeNames[i] )
pSrcRangeNames[i]->ReplaceRangeNamesInUse( aSrcRangeMap );
}
// then update the formulas, they might need the just updated range names
pTab[nDestPos]->ReplaceRangeNamesInUse( 0, 0, MAXCOL, MAXROW, aSrcRangeMap );
}
if ( pSrcRangeNames )
delete [] pSrcRangeNames;
SCsTAB nDz = ((SCsTAB)nDestPos) - (SCsTAB)nSrcPos;
2000-09-18 23:16:46 +00:00
pTab[nDestPos]->UpdateReference(URM_COPY, 0, 0, nDestPos,
MAXCOL, MAXROW, nDestPos,
0, 0, nDz, NULL);
// Test for outside absolute references for info box
BOOL bIsAbsRef = pSrcDoc->pTab[nSrcPos]->TestTabRefAbs(nSrcPos);
// Readjust self-contained absolute references to this sheet
pTab[nDestPos]->TestTabRefAbs(nSrcPos);
2000-09-18 23:16:46 +00:00
if (bIsAbsRef)
{
nRetVal += 1;
// InfoBox AbsoluteRefs sind moeglicherweise nicht mehr korrekt!!
2000-09-18 23:16:46 +00:00
}
if (bNamesLost)
{
nRetVal += 2;
// message: duplicate names
}
2000-09-18 23:16:46 +00:00
pTab[nDestPos]->CompileAll();
}
SetNoListening( FALSE );
if ( !bResultsOnly )
pTab[nDestPos]->StartAllListeners();
SetDirty( ScRange( 0, 0, nDestPos, MAXCOL, MAXROW, nDestPos));
2000-09-18 23:16:46 +00:00
if ( bResultsOnly )
pSrcDoc->SetAutoCalc( bOldAutoCalcSrc );
SetAutoCalc( bOldAutoCalc );
// Drawing kopieren
if (bInsertNew)
TransferDrawPage( pSrcDoc, nSrcPos, nDestPos );
}
if (!bValid)
nRetVal = 0;
return nRetVal;
}
// ----------------------------------------------------------------------------
void ScDocument::SetError( SCCOL nCol, SCROW nRow, SCTAB nTab, const USHORT nError)
2000-09-18 23:16:46 +00:00
{
if (VALIDTAB(nTab))
if (pTab[nTab])
pTab[nTab]->SetError( nCol, nRow, nError );
}
void ScDocument::EraseNonUsedSharedNames(USHORT nLevel)
{
for (USHORT i = 0; i < pRangeName->GetCount(); i++)
{
ScRangeData* pRangeData = (*pRangeName)[i];
if (pRangeData && pRangeData->HasType(RT_SHARED))
{
String aName;
pRangeData->GetName(aName);
aName.Erase(0, 6); // !!! vgl. Table4, FillFormula !!
USHORT nInd = (USHORT) aName.ToInt32();
if (nInd <= nLevel)
{
USHORT nIndex = pRangeData->GetIndex();
BOOL bInUse = FALSE;
for (SCTAB j = 0; !bInUse && (j <= MAXTAB); j++)
2000-09-18 23:16:46 +00:00
{
if (pTab[j])
bInUse = pTab[j]->IsRangeNameInUse(0, 0, MAXCOL-1, MAXROW-1,
nIndex);
}
if (!bInUse)
pRangeName->AtFree(i);
}
}
}
}
// ----------------------------------------------------------------------------
void ScDocument::SetConsolidateDlgData( const ScConsolidateParam* pData )
{
delete pConsolidateDlgData;
if ( pData )
pConsolidateDlgData = new ScConsolidateParam( *pData );
else
pConsolidateDlgData = NULL;
}
void ScDocument::SetChangeViewSettings(const ScChangeViewSettings& rNew)
{
if (pChangeViewSettings==NULL)
pChangeViewSettings = new ScChangeViewSettings;
DBG_ASSERT( pChangeViewSettings, "Oops. No ChangeViewSettings :-( by!" );
*pChangeViewSettings=rNew;
}
2001-11-26 08:28:27 +00:00
// ----------------------------------------------------------------------------
2000-09-18 23:16:46 +00:00
2001-11-26 08:28:27 +00:00
ScFieldEditEngine* ScDocument::CreateFieldEditEngine()
{
ScFieldEditEngine* pNewEditEngine = NULL;
2001-11-26 08:28:27 +00:00
if (!pCacheFieldEditEngine)
{
pNewEditEngine = new ScFieldEditEngine( GetEnginePool(),
2001-11-26 08:28:27 +00:00
GetEditPool(), FALSE );
}
else
{
if ( !bImportingXML )
{
// #i66209# previous use might not have restored update mode,
// ensure same state as for a new EditEngine (UpdateMode = TRUE)
if ( !pCacheFieldEditEngine->GetUpdateMode() )
pCacheFieldEditEngine->SetUpdateMode(TRUE);
}
pNewEditEngine = pCacheFieldEditEngine;
2001-11-26 08:28:27 +00:00
pCacheFieldEditEngine = NULL;
}
return pNewEditEngine;
2001-11-26 08:28:27 +00:00
}
2000-09-18 23:16:46 +00:00
2001-11-26 08:28:27 +00:00
void ScDocument::DisposeFieldEditEngine(ScFieldEditEngine*& rpEditEngine)
{
if (!pCacheFieldEditEngine && rpEditEngine)
{
pCacheFieldEditEngine = rpEditEngine;
pCacheFieldEditEngine->Clear();
}
else
delete rpEditEngine;
rpEditEngine = NULL;
}
2000-09-18 23:16:46 +00:00
// ----------------------------------------------------------------------------
// static
ScRecursionHelper* ScDocument::CreateRecursionHelperInstance()
{
return new ScRecursionHelper;
}
// ----------------------------------------------------------------------------
ScLookupCache & ScDocument::GetLookupCache( const ScRange & rRange )
{
ScLookupCache* pCache = 0;
if (!pLookupCacheMapImpl)
pLookupCacheMapImpl = new ScLookupCacheMapImpl;
ScLookupCacheMap::iterator it( pLookupCacheMapImpl->aCacheMap.find( rRange));
if (it == pLookupCacheMapImpl->aCacheMap.end())
{
pCache = new ScLookupCache( this, rRange);
AddLookupCache( *pCache);
}
else
pCache = (*it).second;
return *pCache;
}
void ScDocument::AddLookupCache( ScLookupCache & rCache )
{
if (!pLookupCacheMapImpl->aCacheMap.insert( ::std::pair< const ScRange,
ScLookupCache*>( rCache.getRange(), &rCache)).second)
{
DBG_ERRORFILE( "ScDocument::AddLookupCache: couldn't add to hash map");
}
else
StartListeningArea( rCache.getRange(), &rCache);
}
void ScDocument::RemoveLookupCache( ScLookupCache & rCache )
{
ScLookupCacheMap::iterator it( pLookupCacheMapImpl->aCacheMap.find(
rCache.getRange()));
if (it == pLookupCacheMapImpl->aCacheMap.end())
{
DBG_ERRORFILE( "ScDocument::RemoveLookupCache: range not found in hash map");
}
else
{
ScLookupCache* pCache = (*it).second;
pLookupCacheMapImpl->aCacheMap.erase( it);
EndListeningArea( pCache->getRange(), &rCache);
}
}
void ScDocument::ClearLookupCaches()
{
if( pLookupCacheMapImpl )
pLookupCacheMapImpl->clear();
}