summaryrefslogtreecommitdiff
path: root/sc/source/core/data/documen3.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/data/documen3.cxx')
-rw-r--r--sc/source/core/data/documen3.cxx2128
1 files changed, 2128 insertions, 0 deletions
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
new file mode 100644
index 000000000000..8fea4b8af2b9
--- /dev/null
+++ b/sc/source/core/data/documen3.cxx
@@ -0,0 +1,2128 @@
+/*************************************************************************
+ *
+ * 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 ---------------------------------------------------------------
+
+#include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
+#include "scitems.hxx"
+#include <editeng/langitem.hxx>
+#include <svl/srchitem.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <sfx2/bindings.hxx>
+#include <sfx2/objsh.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/PasswordHelper.hxx>
+#include <vcl/svapp.hxx>
+#include "document.hxx"
+#include "attrib.hxx"
+#include "cell.hxx"
+#include "table.hxx"
+#include "rangenam.hxx"
+#include "dbcolect.hxx"
+#include "pivot.hxx"
+#include "docpool.hxx"
+#include "poolhelp.hxx"
+#include "autoform.hxx"
+#include "rangelst.hxx"
+#include "chartarr.hxx"
+#include "chartlock.hxx"
+#include "refupdat.hxx"
+#include "docoptio.hxx"
+#include "viewopti.hxx"
+#include "scextopt.hxx"
+#include "brdcst.hxx"
+#include "bcaslot.hxx"
+#include "tablink.hxx"
+#include "externalrefmgr.hxx"
+#include "markdata.hxx"
+#include "validat.hxx"
+#include "dociter.hxx"
+#include "detdata.hxx"
+#include "detfunc.hxx"
+#include "scmod.hxx" // SC_MOD
+#include "inputopt.hxx" // GetExpandRefs
+#include "chartlis.hxx"
+#include "sc.hrc" // SID_LINK
+#include "hints.hxx"
+#include "dpobject.hxx"
+#include "unoguard.hxx"
+#include "drwlayer.hxx"
+#include "unoreflist.hxx"
+#include "listenercalls.hxx"
+// Wang Xu Ming -- 2009-8-17
+// DataPilot Migration - Cache&&Performance
+#include "dpshttab.hxx"
+#include "dptablecache.hxx"
+// End Comments
+#include "tabprotection.hxx"
+#include "formulaparserpool.hxx"
+#include "clipparam.hxx"
+#include "sheetevents.hxx"
+
+#include <memory>
+
+using namespace com::sun::star;
+
+//------------------------------------------------------------------------
+
+ScRangeName* ScDocument::GetRangeName()
+{
+ return pRangeName;
+}
+
+void ScDocument::SetRangeName( ScRangeName* pNewRangeName )
+{
+ if (pRangeName)
+ delete pRangeName;
+ pRangeName = pNewRangeName;
+}
+
+//UNUSED2008-05 ScRangeData* ScDocument::GetRangeAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab,
+//UNUSED2008-05 BOOL bStartOnly) const
+//UNUSED2008-05 {
+//UNUSED2008-05 if ( pRangeName )
+//UNUSED2008-05 return pRangeName->GetRangeAtCursor( ScAddress( nCol, nRow, nTab ), bStartOnly );
+//UNUSED2008-05 else
+//UNUSED2008-05 return NULL;
+//UNUSED2008-05 }
+
+ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, String* pName ) const
+{
+ ScRangeData* pData = NULL;
+ if ( pRangeName )
+ {
+ pData = pRangeName->GetRangeAtBlock( rBlock );
+ if (pData && pName)
+ *pName = pData->GetName();
+ }
+ return pData;
+}
+
+ScDBCollection* ScDocument::GetDBCollection() const
+{
+ return pDBCollection;
+}
+
+void ScDocument::SetDBCollection( ScDBCollection* pNewDBCollection, BOOL bRemoveAutoFilter )
+{
+ if ( bRemoveAutoFilter )
+ {
+ // remove auto filter attribute if new db data don't contain auto filter flag
+ // start position is also compared, so bRemoveAutoFilter must not be set from ref-undo!
+
+ if ( pDBCollection )
+ {
+ USHORT nOldCount = pDBCollection->GetCount();
+ for (USHORT nOld=0; nOld<nOldCount; nOld++)
+ {
+ ScDBData* pOldData = (*pDBCollection)[nOld];
+ if ( pOldData->HasAutoFilter() )
+ {
+ ScRange aOldRange;
+ pOldData->GetArea( aOldRange );
+
+ BOOL bFound = FALSE;
+ USHORT nNewIndex = 0;
+ if ( pNewDBCollection &&
+ pNewDBCollection->SearchName( pOldData->GetName(), nNewIndex ) )
+ {
+ ScDBData* pNewData = (*pNewDBCollection)[nNewIndex];
+ if ( pNewData->HasAutoFilter() )
+ {
+ ScRange aNewRange;
+ pNewData->GetArea( aNewRange );
+ if ( aOldRange.aStart == aNewRange.aStart )
+ bFound = TRUE;
+ }
+ }
+
+ if ( !bFound )
+ {
+ aOldRange.aEnd.SetRow( aOldRange.aStart.Row() );
+ RemoveFlagsTab( aOldRange.aStart.Col(), aOldRange.aStart.Row(),
+ aOldRange.aEnd.Col(), aOldRange.aEnd.Row(),
+ aOldRange.aStart.Tab(), SC_MF_AUTO );
+ if (pShell)
+ pShell->Broadcast( ScPaintHint( aOldRange, PAINT_GRID ) );
+ }
+ }
+ }
+ }
+ }
+
+ if (pDBCollection)
+ delete pDBCollection;
+ pDBCollection = pNewDBCollection;
+}
+
+ScDBData* ScDocument::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, BOOL bStartOnly) const
+{
+ if (pDBCollection)
+ return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly);
+ else
+ return NULL;
+}
+
+ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
+{
+ if (pDBCollection)
+ return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2);
+ else
+ return NULL;
+}
+
+ScDPCollection* ScDocument::GetDPCollection()
+{
+ if (!pDPCollection)
+ pDPCollection = new ScDPCollection(this);
+ return pDPCollection;
+}
+
+ScDPObject* ScDocument::GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
+{
+ if (!pDPCollection)
+ return NULL;
+
+ USHORT nCount = pDPCollection->GetCount();
+ ScAddress aPos( nCol, nRow, nTab );
+ for (USHORT i=0; i<nCount; i++)
+ if ( (*pDPCollection)[i]->GetOutRange().In( aPos ) )
+ return (*pDPCollection)[i];
+
+ return NULL;
+}
+
+ScDPObject* ScDocument::GetDPAtBlock( const ScRange & rBlock ) const
+{
+ if (!pDPCollection)
+ return NULL;
+
+ /* Walk the collection in reverse order to get something of an
+ * approximation of MS Excels 'most recent' effect. */
+ USHORT i = pDPCollection->GetCount();
+ while ( i-- > 0 )
+ if ( (*pDPCollection)[i]->GetOutRange().In( rBlock ) )
+ return (*pDPCollection)[i];
+
+ return NULL;
+}
+
+ScChartCollection* ScDocument::GetChartCollection() const
+{
+ return pChartCollection;
+}
+
+void ScDocument::StopTemporaryChartLock()
+{
+ if( apTemporaryChartLock.get() )
+ apTemporaryChartLock->StopLocking();
+}
+
+void ScDocument::SetChartListenerCollection(
+ ScChartListenerCollection* pNewChartListenerCollection,
+ BOOL bSetChartRangeLists )
+{
+ ScChartListenerCollection* pOld = pChartListenerCollection;
+ pChartListenerCollection = pNewChartListenerCollection;
+ if ( pChartListenerCollection )
+ {
+ if ( pOld )
+ pChartListenerCollection->SetDiffDirty( *pOld, bSetChartRangeLists );
+ pChartListenerCollection->StartAllListeners();
+ }
+ delete pOld;
+}
+
+void ScDocument::SetScenario( SCTAB nTab, BOOL bFlag )
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ pTab[nTab]->SetScenario(bFlag);
+}
+
+BOOL ScDocument::IsScenario( SCTAB nTab ) const
+{
+ return ValidTab(nTab) && pTab[nTab] &&pTab[nTab]->IsScenario();
+ //if (ValidTab(nTab) && pTab[nTab])
+ // return pTab[nTab]->IsScenario();
+
+ //return FALSE;
+}
+
+void ScDocument::SetScenarioData( SCTAB nTab, const String& rComment,
+ const Color& rColor, USHORT nFlags )
+{
+ if (ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsScenario())
+ {
+ pTab[nTab]->SetScenarioComment( rComment );
+ pTab[nTab]->SetScenarioColor( rColor );
+ pTab[nTab]->SetScenarioFlags( nFlags );
+ }
+}
+
+Color ScDocument::GetTabBgColor( SCTAB nTab ) const
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ return pTab[nTab]->GetTabBgColor();
+ return Color(COL_AUTO);
+}
+
+void ScDocument::SetTabBgColor( SCTAB nTab, const Color& rColor )
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ pTab[nTab]->SetTabBgColor(rColor);
+}
+
+bool ScDocument::IsDefaultTabBgColor( SCTAB nTab ) const
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ return pTab[nTab]->GetTabBgColor() == COL_AUTO;
+ return true;
+}
+
+void ScDocument::GetScenarioData( SCTAB nTab, String& rComment,
+ Color& rColor, USHORT& rFlags ) const
+{
+ if (ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsScenario())
+ {
+ pTab[nTab]->GetScenarioComment( rComment );
+ rColor = pTab[nTab]->GetScenarioColor();
+ rFlags = pTab[nTab]->GetScenarioFlags();
+ }
+}
+
+void ScDocument::GetScenarioFlags( SCTAB nTab, USHORT& rFlags ) const
+{
+ if (VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->IsScenario())
+ rFlags = pTab[nTab]->GetScenarioFlags();
+}
+
+BOOL ScDocument::IsLinked( SCTAB nTab ) const
+{
+ return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsLinked();
+ // euqivalent to
+ //if (ValidTab(nTab) && pTab[nTab])
+ // return pTab[nTab]->IsLinked();
+ //return FALSE;
+}
+
+formula::FormulaGrammar::AddressConvention ScDocument::GetAddressConvention() const
+{
+ return formula::FormulaGrammar::extractRefConvention(eGrammar);
+}
+
+formula::FormulaGrammar::Grammar ScDocument::GetGrammar() const
+{
+ return eGrammar;
+}
+
+void ScDocument::SetGrammar( formula::FormulaGrammar::Grammar eGram )
+{
+ eGrammar = eGram;
+}
+
+BOOL ScDocument::GetLinkMode( SCTAB nTab ) const
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ return pTab[nTab]->GetLinkMode();
+ return SC_LINK_NONE;
+}
+
+const String& ScDocument::GetLinkDoc( SCTAB nTab ) const
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ return pTab[nTab]->GetLinkDoc();
+ return EMPTY_STRING;
+}
+
+const String& ScDocument::GetLinkFlt( SCTAB nTab ) const
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ return pTab[nTab]->GetLinkFlt();
+ return EMPTY_STRING;
+}
+
+const String& ScDocument::GetLinkOpt( SCTAB nTab ) const
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ return pTab[nTab]->GetLinkOpt();
+ return EMPTY_STRING;
+}
+
+const String& ScDocument::GetLinkTab( SCTAB nTab ) const
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ return pTab[nTab]->GetLinkTab();
+ return EMPTY_STRING;
+}
+
+ULONG ScDocument::GetLinkRefreshDelay( SCTAB nTab ) const
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ return pTab[nTab]->GetLinkRefreshDelay();
+ return 0;
+}
+
+void ScDocument::SetLink( SCTAB nTab, BYTE nMode, const String& rDoc,
+ const String& rFilter, const String& rOptions,
+ const String& rTabName, ULONG nRefreshDelay )
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ pTab[nTab]->SetLink( nMode, rDoc, rFilter, rOptions, rTabName, nRefreshDelay );
+}
+
+BOOL ScDocument::HasLink( const String& rDoc,
+ const String& rFilter, const String& rOptions ) const
+{
+ SCTAB nCount = GetTableCount();
+ for (SCTAB i=0; i<nCount; i++)
+ if (pTab[i]->IsLinked()
+ && pTab[i]->GetLinkDoc() == rDoc
+ && pTab[i]->GetLinkFlt() == rFilter
+ && pTab[i]->GetLinkOpt() == rOptions)
+ return TRUE;
+
+ return FALSE;
+}
+
+BOOL ScDocument::LinkExternalTab( SCTAB& rTab, const String& aDocTab,
+ const String& aFileName, const String& aTabName )
+{
+ if ( IsClipboard() )
+ {
+ DBG_ERRORFILE( "LinkExternalTab in Clipboard" );
+ return FALSE;
+ }
+ rTab = 0;
+ String aFilterName; // wird vom Loader gefuellt
+ String aOptions; // Filter-Optionen
+ sal_uInt32 nLinkCnt = pExtDocOptions ? pExtDocOptions->GetDocSettings().mnLinkCnt : 0;
+ ScDocumentLoader aLoader( aFileName, aFilterName, aOptions, nLinkCnt + 1 );
+ if ( aLoader.IsError() )
+ return FALSE;
+ ScDocument* pSrcDoc = aLoader.GetDocument();
+
+ // Tabelle kopieren
+ SCTAB nSrcTab;
+ if ( pSrcDoc->GetTable( aTabName, nSrcTab ) )
+ {
+ if ( !InsertTab( SC_TAB_APPEND, aDocTab, TRUE ) )
+ {
+ DBG_ERRORFILE("can't insert external document table");
+ return FALSE;
+ }
+ rTab = GetTableCount() - 1;
+ // nicht neu einfuegen, nur Ergebnisse
+ TransferTab( pSrcDoc, nSrcTab, rTab, FALSE, TRUE );
+ }
+ else
+ return FALSE;
+
+ ULONG nRefreshDelay = 0;
+
+ BOOL bWasThere = HasLink( aFileName, aFilterName, aOptions );
+ SetLink( rTab, SC_LINK_VALUE, aFileName, aFilterName, aOptions, aTabName, nRefreshDelay );
+ if ( !bWasThere ) // Link pro Quelldokument nur einmal eintragen
+ {
+ ScTableLink* pLink = new ScTableLink( pShell, aFileName, aFilterName, aOptions, nRefreshDelay );
+ pLink->SetInCreate( TRUE );
+ GetLinkManager()->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName,
+ &aFilterName );
+ pLink->Update();
+ pLink->SetInCreate( FALSE );
+ SfxBindings* pBindings = GetViewBindings();
+ if (pBindings)
+ pBindings->Invalidate( SID_LINKS );
+ }
+ return TRUE;
+}
+
+ScExternalRefManager* ScDocument::GetExternalRefManager() const
+{
+ ScDocument* pThis = const_cast<ScDocument*>(this);
+ if (!pExternalRefMgr.get())
+ pThis->pExternalRefMgr.reset( new ScExternalRefManager( pThis));
+
+ return pExternalRefMgr.get();
+}
+
+bool ScDocument::IsInExternalReferenceMarking() const
+{
+ return pExternalRefMgr.get() && pExternalRefMgr->isInReferenceMarking();
+}
+
+void ScDocument::MarkUsedExternalReferences()
+{
+ if (!pExternalRefMgr.get())
+ return;
+ if (!pExternalRefMgr->hasExternalData())
+ return;
+ // Charts.
+ bool bAllMarked = pExternalRefMgr->markUsedByLinkListeners();
+ // Formula cells.
+ bAllMarked = pExternalRefMgr->markUsedExternalRefCells();
+
+ /* NOTE: Conditional formats and validation objects are marked when
+ * collecting them during export. */
+}
+
+ScFormulaParserPool& ScDocument::GetFormulaParserPool() const
+{
+ if( !mxFormulaParserPool.get() )
+ mxFormulaParserPool.reset( new ScFormulaParserPool( *this ) );
+ return *mxFormulaParserPool;
+}
+
+const ScSheetEvents* ScDocument::GetSheetEvents( SCTAB nTab ) const
+{
+ if (VALIDTAB(nTab) && pTab[nTab])
+ return pTab[nTab]->GetSheetEvents();
+ return NULL;
+}
+
+void ScDocument::SetSheetEvents( SCTAB nTab, const ScSheetEvents* pNew )
+{
+ if (VALIDTAB(nTab) && pTab[nTab])
+ pTab[nTab]->SetSheetEvents( pNew );
+}
+
+bool ScDocument::HasSheetEventScript( SCTAB nTab, sal_Int32 nEvent, bool bWithVbaEvents ) const
+{
+ if (pTab[nTab])
+ {
+ // check if any event handler script has been configured
+ const ScSheetEvents* pEvents = pTab[nTab]->GetSheetEvents();
+ if ( pEvents && pEvents->GetScript( nEvent ) )
+ return true;
+ // check if VBA event handlers exist
+ if (bWithVbaEvents && mxVbaEvents.is()) try
+ {
+ uno::Sequence< uno::Any > aArgs( 1 );
+ aArgs[ 0 ] <<= nTab;
+ if (mxVbaEvents->hasVbaEventHandler( ScSheetEvents::GetVbaSheetEventId( nEvent ), aArgs ) ||
+ mxVbaEvents->hasVbaEventHandler( ScSheetEvents::GetVbaDocumentEventId( nEvent ), uno::Sequence< uno::Any >() ))
+ return true;
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ return false;
+}
+
+bool ScDocument::HasAnySheetEventScript( sal_Int32 nEvent, bool bWithVbaEvents ) const
+{
+ for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++)
+ if (HasSheetEventScript( nTab, nEvent, bWithVbaEvents ))
+ return true;
+ return false;
+}
+
+BOOL ScDocument::HasCalcNotification( SCTAB nTab ) const
+{
+ if (VALIDTAB(nTab) && pTab[nTab])
+ return pTab[nTab]->GetCalcNotification();
+ return FALSE;
+}
+
+void ScDocument::SetCalcNotification( SCTAB nTab )
+{
+ // set only if not set before
+ if (VALIDTAB(nTab) && pTab[nTab] && !pTab[nTab]->GetCalcNotification())
+ pTab[nTab]->SetCalcNotification(TRUE);
+}
+
+void ScDocument::ResetCalcNotifications()
+{
+ for (SCTAB nTab = 0; nTab <= MAXTAB; nTab++)
+ if (pTab[nTab] && pTab[nTab]->GetCalcNotification())
+ pTab[nTab]->SetCalcNotification(FALSE);
+}
+
+ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, BOOL bCreate )
+{
+ ScOutlineTable* pVal = NULL;
+
+ if (VALIDTAB(nTab))
+ if (pTab[nTab])
+ {
+ pVal = pTab[nTab]->GetOutlineTable();
+ if (!pVal)
+ if (bCreate)
+ {
+ pTab[nTab]->StartOutlineTable();
+ pVal = pTab[nTab]->GetOutlineTable();
+ }
+ }
+
+ return pVal;
+}
+
+BOOL ScDocument::SetOutlineTable( SCTAB nTab, const ScOutlineTable* pNewOutline )
+{
+ return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->SetOutlineTable(pNewOutline);
+ //if (VALIDTAB(nTab))
+ // if (pTab[nTab])
+ // return pTab[nTab]->SetOutlineTable(pNewOutline);
+
+ //return FALSE;
+}
+
+void ScDocument::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow,
+ SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
+{
+ if (VALIDTAB(nTab) && pTab[nTab])
+ pTab[nTab]->DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
+}
+
+BOOL ScDocument::TestRemoveSubTotals( SCTAB nTab, const ScSubTotalParam& rParam )
+{
+ return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->TestRemoveSubTotals( rParam );
+ //if (VALIDTAB(nTab) && pTab[nTab] )
+ // return pTab[nTab]->TestRemoveSubTotals( rParam );
+
+ //return FALSE;
+}
+
+void ScDocument::RemoveSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
+{
+ if ( VALIDTAB(nTab) && pTab[nTab] )
+ pTab[nTab]->RemoveSubTotals( rParam );
+}
+
+BOOL ScDocument::DoSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
+{
+ return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->DoSubTotals( rParam );
+ //if (VALIDTAB(nTab))
+ // if (pTab[nTab])
+ // return pTab[nTab]->DoSubTotals( rParam );
+
+ //return FALSE;
+}
+
+BOOL ScDocument::HasSubTotalCells( const ScRange& rRange )
+{
+ ScCellIterator aIter( this, rRange );
+ ScBaseCell* pCell = aIter.GetFirst();
+ while (pCell)
+ {
+ if ( pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->IsSubTotal() )
+ return TRUE;
+
+ pCell = aIter.GetNext();
+ }
+ return FALSE; // none found
+}
+
+// kopiert aus diesem Dokument die Zellen von Positionen, an denen in pPosDoc
+// auch Zellen stehen, nach pDestDoc
+
+void ScDocument::CopyUpdated( ScDocument* pPosDoc, ScDocument* pDestDoc )
+{
+ SCTAB nCount = GetTableCount();
+ for (SCTAB nTab=0; nTab<nCount; nTab++)
+ if (pTab[nTab] && pPosDoc->pTab[nTab] && pDestDoc->pTab[nTab])
+ pTab[nTab]->CopyUpdated( pPosDoc->pTab[nTab], pDestDoc->pTab[nTab] );
+}
+
+void ScDocument::CopyScenario( SCTAB nSrcTab, SCTAB nDestTab, BOOL bNewScenario )
+{
+ if (ValidTab(nSrcTab) && ValidTab(nDestTab) && pTab[nSrcTab] && pTab[nDestTab])
+ {
+ // Flags fuer aktive Szenarios richtig setzen
+ // und aktuelle Werte in bisher aktive Szenarios zurueckschreiben
+
+ ScRangeList aRanges = *pTab[nSrcTab]->GetScenarioRanges();
+ const ULONG nRangeCount = aRanges.Count();
+
+ // nDestTab ist die Zieltabelle
+ for ( SCTAB nTab = nDestTab+1;
+ nTab<=MAXTAB && pTab[nTab] && pTab[nTab]->IsScenario();
+ nTab++ )
+ {
+ if ( pTab[nTab]->IsActiveScenario() ) // auch wenn's dasselbe Szenario ist
+ {
+ BOOL bTouched = FALSE;
+ for ( ULONG nR=0; nR<nRangeCount && !bTouched; nR++)
+ {
+ const ScRange* pRange = aRanges.GetObject(nR);
+ if ( pTab[nTab]->HasScenarioRange( *pRange ) )
+ bTouched = TRUE;
+ }
+ if (bTouched)
+ {
+ pTab[nTab]->SetActiveScenario(FALSE);
+ if ( pTab[nTab]->GetScenarioFlags() & SC_SCENARIO_TWOWAY )
+ pTab[nTab]->CopyScenarioFrom( pTab[nDestTab] );
+ }
+ }
+ }
+
+ pTab[nSrcTab]->SetActiveScenario(TRUE); // da kommt's her...
+ if (!bNewScenario) // Daten aus dem ausgewaehlten Szenario kopieren
+ {
+ BOOL bOldAutoCalc = GetAutoCalc();
+ SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
+ pTab[nSrcTab]->CopyScenarioTo( pTab[nDestTab] );
+ SetDirty();
+ SetAutoCalc( bOldAutoCalc );
+ }
+ }
+}
+
+void ScDocument::MarkScenario( SCTAB nSrcTab, SCTAB nDestTab, ScMarkData& rDestMark,
+ BOOL bResetMark, USHORT nNeededBits ) const
+{
+ if (bResetMark)
+ rDestMark.ResetMark();
+
+ if (ValidTab(nSrcTab) && pTab[nSrcTab])
+ pTab[nSrcTab]->MarkScenarioIn( rDestMark, nNeededBits );
+
+ rDestMark.SetAreaTab( nDestTab );
+}
+
+BOOL ScDocument::HasScenarioRange( SCTAB nTab, const ScRange& rRange ) const
+{
+ return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->HasScenarioRange( rRange );
+ //if (ValidTab(nTab) && pTab[nTab])
+ // return pTab[nTab]->HasScenarioRange( rRange );
+
+ //return FALSE;
+}
+
+const ScRangeList* ScDocument::GetScenarioRanges( SCTAB nTab ) const
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ return pTab[nTab]->GetScenarioRanges();
+
+ return NULL;
+}
+
+BOOL ScDocument::IsActiveScenario( SCTAB nTab ) const
+{
+ return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsActiveScenario( );
+ //if (ValidTab(nTab) && pTab[nTab])
+ // return pTab[nTab]->IsActiveScenario();
+
+ //return FALSE;
+}
+
+void ScDocument::SetActiveScenario( SCTAB nTab, BOOL bActive )
+{
+ if (ValidTab(nTab) && pTab[nTab])
+ pTab[nTab]->SetActiveScenario( bActive );
+}
+
+BOOL ScDocument::TestCopyScenario( SCTAB nSrcTab, SCTAB nDestTab ) const
+{
+ if (ValidTab(nSrcTab) && ValidTab(nDestTab))
+ return pTab[nSrcTab]->TestCopyScenarioTo( pTab[nDestTab] );
+
+ DBG_ERROR("falsche Tabelle bei TestCopyScenario");
+ return FALSE;
+}
+
+void ScDocument::AddUnoObject( SfxListener& rObject )
+{
+ if (!pUnoBroadcaster)
+ pUnoBroadcaster = new SfxBroadcaster;
+
+ rObject.StartListening( *pUnoBroadcaster );
+}
+
+void ScDocument::RemoveUnoObject( SfxListener& rObject )
+{
+ if (pUnoBroadcaster)
+ {
+ rObject.EndListening( *pUnoBroadcaster );
+
+ if ( bInUnoBroadcast )
+ {
+ // #107294# Broadcasts from ScDocument::BroadcastUno are the only way that
+ // uno object methods are called without holding a reference.
+ //
+ // If RemoveUnoObject is called from an object dtor in the finalizer thread
+ // while the main thread is calling BroadcastUno, the dtor thread must wait
+ // (or the object's Notify might try to access a deleted object).
+ // The SolarMutex can't be locked here because if a component is called from
+ // a VCL event, the main thread has the SolarMutex locked all the time.
+ //
+ // This check is done after calling EndListening, so a later BroadcastUno call
+ // won't touch this object.
+
+ vos::IMutex& rSolarMutex = Application::GetSolarMutex();
+ if ( rSolarMutex.tryToAcquire() )
+ {
+ // BroadcastUno is always called with the SolarMutex locked, so if it
+ // can be acquired, this is within the same thread (should not happen)
+ DBG_ERRORFILE( "RemoveUnoObject called from BroadcastUno" );
+ rSolarMutex.release();
+ }
+ else
+ {
+ // let the thread that called BroadcastUno continue
+ while ( bInUnoBroadcast )
+ {
+ vos::OThread::yield();
+ }
+ }
+ }
+ }
+ else
+ {
+ DBG_ERROR("No Uno broadcaster");
+ }
+}
+
+void ScDocument::BroadcastUno( const SfxHint &rHint )
+{
+ if (pUnoBroadcaster)
+ {
+ bInUnoBroadcast = TRUE;
+ pUnoBroadcaster->Broadcast( rHint );
+ bInUnoBroadcast = FALSE;
+
+ // During Broadcast notification, Uno objects can add to pUnoListenerCalls.
+ // The listener calls must be processed after completing the broadcast,
+ // because they can add or remove objects from pUnoBroadcaster.
+
+ if ( pUnoListenerCalls && rHint.ISA( SfxSimpleHint ) &&
+ ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DATACHANGED &&
+ !bInUnoListenerCall )
+ {
+ // Listener calls may lead to BroadcastUno calls again. The listener calls
+ // are not nested, instead the calls are collected in the list, and the
+ // outermost call executes them all.
+
+ ScChartLockGuard aChartLockGuard(this);
+ bInUnoListenerCall = TRUE;
+ pUnoListenerCalls->ExecuteAndClear();
+ bInUnoListenerCall = FALSE;
+ }
+ }
+}
+
+void ScDocument::AddUnoListenerCall( const uno::Reference<util::XModifyListener>& rListener,
+ const lang::EventObject& rEvent )
+{
+ DBG_ASSERT( bInUnoBroadcast, "AddUnoListenerCall is supposed to be called from BroadcastUno only" );
+
+ if ( !pUnoListenerCalls )
+ pUnoListenerCalls = new ScUnoListenerCalls;
+ pUnoListenerCalls->Add( rListener, rEvent );
+}
+
+void ScDocument::BeginUnoRefUndo()
+{
+ DBG_ASSERT( !pUnoRefUndoList, "BeginUnoRefUndo twice" );
+ delete pUnoRefUndoList;
+
+ pUnoRefUndoList = new ScUnoRefList;
+}
+
+ScUnoRefList* ScDocument::EndUnoRefUndo()
+{
+ ScUnoRefList* pRet = pUnoRefUndoList;
+ pUnoRefUndoList = NULL;
+ return pRet; // must be deleted by caller!
+}
+
+void ScDocument::AddUnoRefChange( sal_Int64 nId, const ScRangeList& rOldRanges )
+{
+ if ( pUnoRefUndoList )
+ pUnoRefUndoList->Add( nId, rOldRanges );
+}
+
+sal_Int64 ScDocument::GetNewUnoId()
+{
+ return ++nUnoObjectId;
+}
+
+void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode,
+ SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
+ SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
+ SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
+ ScDocument* pUndoDoc, BOOL bIncludeDraw,
+ bool bUpdateNoteCaptionPos )
+{
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ PutInOrder( nTab1, nTab2 );
+ if (VALIDTAB(nTab1) && VALIDTAB(nTab2))
+ {
+ BOOL bExpandRefsOld = IsExpandRefs();
+ if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
+ SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
+ SCTAB i;
+ SCTAB iMax;
+ if ( eUpdateRefMode == URM_COPY )
+ {
+ i = nTab1;
+ iMax = nTab2;
+ }
+ else
+ {
+ ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ xColNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
+ xRowNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
+ pDBCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
+ pRangeName->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
+ if ( pDPCollection )
+ pDPCollection->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
+ UpdateChartRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
+ UpdateRefAreaLinks( eUpdateRefMode, aRange, nDx, nDy, nDz );
+ if ( pCondFormList )
+ pCondFormList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
+ if ( pValidationList )
+ pValidationList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
+ if ( pDetOpList )
+ pDetOpList->UpdateReference( this, eUpdateRefMode, aRange, nDx, nDy, nDz );
+ if ( pUnoBroadcaster )
+ pUnoBroadcaster->Broadcast( ScUpdateRefHint(
+ eUpdateRefMode, aRange, nDx, nDy, nDz ) );
+ i = 0;
+ iMax = MAXTAB;
+ }
+ for ( ; i<=iMax; i++)
+ if (pTab[i])
+ pTab[i]->UpdateReference(
+ eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
+ nDx, nDy, nDz, pUndoDoc, bIncludeDraw, bUpdateNoteCaptionPos );
+
+ if ( bIsEmbedded )
+ {
+ SCCOL theCol1;
+ SCROW theRow1;
+ SCTAB theTab1;
+ SCCOL theCol2;
+ SCROW theRow2;
+ SCTAB theTab2;
+ theCol1 = aEmbedRange.aStart.Col();
+ theRow1 = aEmbedRange.aStart.Row();
+ theTab1 = aEmbedRange.aStart.Tab();
+ theCol2 = aEmbedRange.aEnd.Col();
+ theRow2 = aEmbedRange.aEnd.Row();
+ theTab2 = aEmbedRange.aEnd.Tab();
+ if ( ScRefUpdate::Update( this, eUpdateRefMode, nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
+ nDx,nDy,nDz, theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
+ {
+ aEmbedRange = ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
+ }
+ }
+ SetExpandRefs( bExpandRefsOld );
+
+ // #30428# after moving, no clipboard move ref-updates are possible
+ if ( eUpdateRefMode != URM_COPY && IsClipboardSource() )
+ {
+ ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
+ if (pClipDoc)
+ pClipDoc->GetClipParam().mbCutMode = false;
+ }
+ }
+}
+
+void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDoc,
+ const ScMarkData& rMark, ScDocument* pUndoDoc )
+{
+ DBG_ASSERT(pClipDoc->bIsClip, "UpdateTranspose: kein Clip");
+
+ ScRange aSource;
+ ScClipParam& rClipParam = GetClipParam();
+ if (rClipParam.maRanges.Count())
+ aSource = *rClipParam.maRanges.First();
+ ScAddress aDest = rDestPos;
+
+ SCTAB nClipTab = 0;
+ for (SCTAB nDestTab=0; nDestTab<=MAXTAB && pTab[nDestTab]; nDestTab++)
+ if (rMark.GetTableSelect(nDestTab))
+ {
+ while (!pClipDoc->pTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
+ aSource.aStart.SetTab( nClipTab );
+ aSource.aEnd.SetTab( nClipTab );
+ aDest.SetTab( nDestTab );
+
+ // wie UpdateReference
+
+ pRangeName->UpdateTranspose( aSource, aDest ); // vor den Zellen!
+ for (SCTAB i=0; i<=MAXTAB; i++)
+ if (pTab[i])
+ pTab[i]->UpdateTranspose( aSource, aDest, pUndoDoc );
+
+ nClipTab = (nClipTab+1) % (MAXTAB+1);
+ }
+}
+
+void ScDocument::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
+{
+ //! pDBCollection
+ //! pPivotCollection
+ //! UpdateChartRef
+
+ pRangeName->UpdateGrow( rArea, nGrowX, nGrowY );
+
+ for (SCTAB i=0; i<=MAXTAB && pTab[i]; i++)
+ pTab[i]->UpdateGrow( rArea, nGrowX, nGrowY );
+}
+
+void ScDocument::Fill(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
+ ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
+ double nStepValue, double nMaxValue)
+{
+ PutInOrder( nCol1, nCol2 );
+ PutInOrder( nRow1, nRow2 );
+ for (SCTAB i=0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->Fill(nCol1, nRow1, nCol2, nRow2,
+ nFillCount, eFillDir, eFillCmd, eFillDateCmd,
+ nStepValue, nMaxValue);
+}
+
+String ScDocument::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
+{
+ SCTAB nTab = rSource.aStart.Tab();
+ if (pTab[nTab])
+ return pTab[nTab]->GetAutoFillPreview( rSource, nEndX, nEndY );
+
+ return EMPTY_STRING;
+}
+
+void ScDocument::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
+ USHORT nFormatNo, const ScMarkData& rMark )
+{
+ PutInOrder( nStartCol, nEndCol );
+ PutInOrder( nStartRow, nEndRow );
+ for (SCTAB i=0; i <= MAXTAB; i++)
+ if (pTab[i])
+ if (rMark.GetTableSelect(i))
+ pTab[i]->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo );
+}
+
+void ScDocument::GetAutoFormatData(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
+ ScAutoFormatData& rData)
+{
+ if (VALIDTAB(nTab))
+ {
+ if (pTab[nTab])
+ {
+ PutInOrder(nStartCol, nEndCol);
+ PutInOrder(nStartRow, nEndRow);
+ pTab[nTab]->GetAutoFormatData(nStartCol, nStartRow, nEndCol, nEndRow, rData);
+ }
+ }
+}
+
+// static
+void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem& rSearchItem,
+ SCCOL& rCol, SCROW& rRow )
+{
+ USHORT nCommand = rSearchItem.GetCommand();
+ BOOL bReplace = ( nCommand == SVX_SEARCHCMD_REPLACE ||
+ nCommand == SVX_SEARCHCMD_REPLACE_ALL );
+ if ( rSearchItem.GetBackward() )
+ {
+ if ( rSearchItem.GetRowDirection() )
+ {
+ if ( rSearchItem.GetPattern() )
+ {
+ rCol = MAXCOL;
+ rRow = MAXROW+1;
+ }
+ else if ( bReplace )
+ {
+ rCol = MAXCOL;
+ rRow = MAXROW;
+ }
+ else
+ {
+ rCol = MAXCOL+1;
+ rRow = MAXROW;
+ }
+ }
+ else
+ {
+ if ( rSearchItem.GetPattern() )
+ {
+ rCol = MAXCOL+1;
+ rRow = MAXROW;
+ }
+ else if ( bReplace )
+ {
+ rCol = MAXCOL;
+ rRow = MAXROW;
+ }
+ else
+ {
+ rCol = MAXCOL;
+ rRow = MAXROW+1;
+ }
+ }
+ }
+ else
+ {
+ if ( rSearchItem.GetRowDirection() )
+ {
+ if ( rSearchItem.GetPattern() )
+ {
+ rCol = 0;
+ rRow = (SCROW) -1;
+ }
+ else if ( bReplace )
+ {
+ rCol = 0;
+ rRow = 0;
+ }
+ else
+ {
+ rCol = (SCCOL) -1;
+ rRow = 0;
+ }
+ }
+ else
+ {
+ if ( rSearchItem.GetPattern() )
+ {
+ rCol = (SCCOL) -1;
+ rRow = 0;
+ }
+ else if ( bReplace )
+ {
+ rCol = 0;
+ rRow = 0;
+ }
+ else
+ {
+ rCol = 0;
+ rRow = (SCROW) -1;
+ }
+ }
+ }
+}
+
+BOOL ScDocument::SearchAndReplace(const SvxSearchItem& rSearchItem,
+ SCCOL& rCol, SCROW& rRow, SCTAB& rTab,
+ ScMarkData& rMark,
+ String& rUndoStr, ScDocument* pUndoDoc)
+{
+ //! getrennte Markierungen pro Tabelle verwalten !!!!!!!!!!!!!
+
+ rMark.MarkToMulti();
+
+ BOOL bFound = FALSE;
+ if (VALIDTAB(rTab))
+ {
+ SCCOL nCol;
+ SCROW nRow;
+ SCTAB nTab;
+ USHORT nCommand = rSearchItem.GetCommand();
+ if ( nCommand == SVX_SEARCHCMD_FIND_ALL ||
+ nCommand == SVX_SEARCHCMD_REPLACE_ALL )
+ {
+ for (nTab = 0; nTab <= MAXTAB; nTab++)
+ if (pTab[nTab])
+ {
+ if (rMark.GetTableSelect(nTab))
+ {
+ nCol = 0;
+ nRow = 0;
+ bFound |= pTab[nTab]->SearchAndReplace(
+ rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
+ }
+ }
+
+ // Markierung wird innen schon komplett gesetzt
+ }
+ else
+ {
+ nCol = rCol;
+ nRow = rRow;
+ if (rSearchItem.GetBackward())
+ {
+ for (nTab = rTab; ((SCsTAB)nTab >= 0) && !bFound; nTab--)
+ if (pTab[nTab])
+ {
+ if (rMark.GetTableSelect(nTab))
+ {
+ bFound = pTab[nTab]->SearchAndReplace(
+ rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
+ if (bFound)
+ {
+ rCol = nCol;
+ rRow = nRow;
+ rTab = nTab;
+ }
+ else
+ ScDocument::GetSearchAndReplaceStart(
+ rSearchItem, nCol, nRow );
+ }
+ }
+ }
+ else
+ {
+ for (nTab = rTab; (nTab <= MAXTAB) && !bFound; nTab++)
+ if (pTab[nTab])
+ {
+ if (rMark.GetTableSelect(nTab))
+ {
+ bFound = pTab[nTab]->SearchAndReplace(
+ rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
+ if (bFound)
+ {
+ rCol = nCol;
+ rRow = nRow;
+ rTab = nTab;
+ }
+ else
+ ScDocument::GetSearchAndReplaceStart(
+ rSearchItem, nCol, nRow );
+ }
+ }
+ }
+ }
+ }
+ return bFound;
+}
+
+// Outline anpassen
+
+BOOL ScDocument::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, BOOL bShow )
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ return pTab[nTab]->UpdateOutlineCol( nStartCol, nEndCol, bShow );
+
+ DBG_ERROR("missing tab");
+ return FALSE;
+}
+
+BOOL ScDocument::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, BOOL bShow )
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ return pTab[nTab]->UpdateOutlineRow( nStartRow, nEndRow, bShow );
+
+ DBG_ERROR("missing tab");
+ return FALSE;
+}
+
+void ScDocument::Sort(SCTAB nTab, const ScSortParam& rSortParam, BOOL bKeepQuery)
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ {
+ BOOL bOldDisableIdle = IsIdleDisabled();
+ DisableIdle( TRUE );
+ pTab[nTab]->Sort(rSortParam, bKeepQuery);
+ DisableIdle( bOldDisableIdle );
+ }
+}
+
+SCSIZE ScDocument::Query(SCTAB nTab, const ScQueryParam& rQueryParam, BOOL bKeepSub)
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ return pTab[nTab]->Query((ScQueryParam&)rQueryParam, bKeepSub);
+
+ DBG_ERROR("missing tab");
+ return 0;
+}
+
+
+BOOL ScDocument::ValidQuery( SCROW nRow, SCTAB nTab, const ScQueryParam& rQueryParam, BOOL* pSpecial )
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ return pTab[nTab]->ValidQuery( nRow, rQueryParam, pSpecial );
+
+ DBG_ERROR("missing tab");
+ return FALSE;
+}
+
+
+void ScDocument::GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, String& rStr)
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ pTab[nTab]->GetUpperCellString( nCol, nRow, rStr );
+ else
+ rStr.Erase();
+}
+
+BOOL ScDocument::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, ScQueryParam& rQueryParam)
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ return pTab[nTab]->CreateQueryParam(nCol1, nRow1, nCol2, nRow2, rQueryParam);
+
+ DBG_ERROR("missing tab");
+ return FALSE;
+}
+
+BOOL ScDocument::HasAutoFilter( SCCOL nCurCol, SCROW nCurRow, SCTAB nCurTab )
+{
+ ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab );
+ BOOL bHasAutoFilter = ( pDBData != NULL );
+
+ if ( pDBData )
+ {
+ if ( pDBData->HasHeader() )
+ {
+ SCCOL nCol;
+ SCROW nRow;
+ INT16 nFlag;
+
+ ScQueryParam aParam;
+ pDBData->GetQueryParam( aParam );
+ nRow = aParam.nRow1;
+
+ for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ )
+ {
+ nFlag = ((ScMergeFlagAttr*)
+ GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))->
+ GetValue();
+
+ if ( (nFlag & SC_MF_AUTO) == 0 )
+ bHasAutoFilter = FALSE;
+ }
+ }
+ else
+ bHasAutoFilter = FALSE;
+ }
+
+ return bHasAutoFilter;
+}
+
+BOOL ScDocument::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
+ SCTAB nTab )
+{
+ return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
+ //if (VALIDTAB(nTab))
+ // if (pTab[nTab])
+ // return pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
+
+ //return FALSE;
+}
+
+BOOL ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
+ SCTAB nTab )
+{
+ return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
+ //if (VALIDTAB(nTab))
+ // if (pTab[nTab])
+ // return pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
+
+ //return FALSE;
+}
+
+//
+// GetFilterEntries - Eintraege fuer AutoFilter-Listbox
+//
+
+BOOL ScDocument::GetFilterEntries(
+ SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates)
+{
+ if ( ValidTab(nTab) && pTab[nTab] && pDBCollection )
+ {
+ ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, FALSE); //!??
+ if (pDBData)
+ {
+ SCTAB nAreaTab;
+ SCCOL nStartCol;
+ SCROW nStartRow;
+ SCCOL nEndCol;
+ SCROW nEndRow;
+ pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
+ if (pDBData->HasHeader())
+ ++nStartRow;
+
+ ScQueryParam aParam;
+ pDBData->GetQueryParam( aParam );
+ rStrings.SetCaseSensitive( aParam.bCaseSens );
+
+ // return all filter entries, if a filter condition is connected with a boolean OR
+ if ( bFilter )
+ {
+ SCSIZE nEntryCount = aParam.GetEntryCount();
+ for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i )
+ {
+ ScQueryEntry& rEntry = aParam.GetEntry(i);
+ if ( rEntry.eConnect != SC_AND )
+ {
+ bFilter = false;
+ break;
+ }
+ }
+ }
+
+ if ( bFilter )
+ {
+ pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates );
+ }
+ else
+ {
+ pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//
+// GetFilterEntriesArea - Eintraege fuer Filter-Dialog
+//
+
+BOOL ScDocument::GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow,
+ SCTAB nTab, TypedScStrCollection& rStrings, bool& rHasDates )
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ {
+ pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//
+// GetDataEntries - Eintraege fuer Auswahlliste-Listbox (keine Zahlen / Formeln)
+//
+
+BOOL ScDocument::GetDataEntries( SCCOL nCol, SCROW nRow, SCTAB nTab,
+ TypedScStrCollection& rStrings, BOOL bLimit )
+{
+ if( !bLimit )
+ {
+ /* Try to generate the list from list validation. This part is skipped,
+ if bLimit==TRUE, because in that case this function is called to get
+ cell values for auto completion on input. */
+ sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
+ if( nValidation )
+ {
+ const ScValidationData* pData = GetValidationEntry( nValidation );
+ if( pData && pData->FillSelectionList( rStrings, ScAddress( nCol, nRow, nTab ) ) )
+ return TRUE;
+ }
+ }
+
+ return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
+ //if (ValidTab(nTab) && pTab[nTab])
+ // return pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
+
+ //return FALSE;
+}
+
+//
+// GetFormulaEntries - Eintraege fuer Formel-AutoEingabe
+//
+
+// Funktionen werden als 1 schon vom InputHandler eingefuegt
+#define SC_STRTYPE_NAMES 2
+#define SC_STRTYPE_DBNAMES 3
+#define SC_STRTYPE_HEADERS 4
+
+BOOL ScDocument::GetFormulaEntries( TypedScStrCollection& rStrings )
+{
+ USHORT i;
+
+ //
+ // Bereichsnamen
+ //
+
+ if ( pRangeName )
+ {
+ USHORT nRangeCount = pRangeName->GetCount();
+ for ( i=0; i<nRangeCount; i++ )
+ {
+ ScRangeData* pData = (*pRangeName)[i];
+ if (pData)
+ {
+ TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_NAMES );
+ if ( !rStrings.Insert(pNew) )
+ delete pNew;
+ }
+ }
+ }
+
+ //
+ // Datenbank-Bereiche
+ //
+
+ if ( pDBCollection )
+ {
+ USHORT nDBCount = pDBCollection->GetCount();
+ for ( i=0; i<nDBCount; i++ )
+ {
+ ScDBData* pData = (*pDBCollection)[i];
+ if (pData)
+ {
+ TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_DBNAMES );
+ if ( !rStrings.Insert(pNew) )
+ delete pNew;
+ }
+ }
+ }
+
+ //
+ // Inhalte von Beschriftungsbereichen
+ //
+
+ ScRangePairList* pLists[2];
+ pLists[0] = GetColNameRanges();
+ pLists[1] = GetRowNameRanges();
+ for (USHORT nListNo=0; nListNo<2; nListNo++)
+ {
+ ScRangePairList* pList = pLists[nListNo];
+ if (pList)
+ for ( ScRangePair* pPair = pList->First(); pPair; pPair = pList->Next() )
+ {
+ ScRange aRange = pPair->GetRange(0);
+ ScCellIterator aIter( this, aRange );
+ for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() )
+ if ( pCell->HasStringData() )
+ {
+ String aStr = pCell->GetStringData();
+ TypedStrData* pNew = new TypedStrData( aStr, 0.0, SC_STRTYPE_HEADERS );
+ if ( !rStrings.Insert(pNew) )
+ delete pNew;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+BOOL ScDocument::IsEmbedded() const
+{
+ return bIsEmbedded;
+}
+
+void ScDocument::GetEmbedded( ScRange& rRange ) const
+{
+ rRange = aEmbedRange;
+}
+
+Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm
+{
+ Rectangle aRect;
+ ScTable* pTable = pTab[aEmbedRange.aStart.Tab()];
+ if (!pTable)
+ {
+ DBG_ERROR("GetEmbeddedRect ohne Tabelle");
+ }
+ else
+ {
+ SCCOL i;
+
+ for (i=0; i<aEmbedRange.aStart.Col(); i++)
+ aRect.Left() += pTable->GetColWidth(i);
+ aRect.Top() += pTable->GetRowHeight( 0, aEmbedRange.aStart.Row() - 1);
+ aRect.Right() = aRect.Left();
+ for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++)
+ aRect.Right() += pTable->GetColWidth(i);
+ aRect.Bottom() = aRect.Top();
+ aRect.Bottom() += pTable->GetRowHeight( aEmbedRange.aStart.Row(), aEmbedRange.aEnd.Row());
+
+ aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS );
+ aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS );
+ aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS );
+ aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS );
+ }
+ return aRect;
+}
+
+void ScDocument::SetEmbedded( const ScRange& rRange )
+{
+ bIsEmbedded = TRUE;
+ aEmbedRange = rRange;
+}
+
+void ScDocument::ResetEmbedded()
+{
+ bIsEmbedded = FALSE;
+ aEmbedRange = ScRange();
+}
+
+
+/** Similar to ScViewData::AddPixelsWhile(), but add height twips and only
+ while result is less than nStopTwips.
+ @return TRUE if advanced at least one row.
+ */
+bool lcl_AddTwipsWhile( long & rTwips, long nStopTwips, SCROW & rPosY, SCROW nEndRow, const ScTable * pTable )
+{
+ SCROW nRow = rPosY;
+ bool bAdded = false;
+ bool bStop = false;
+ while (rTwips < nStopTwips && nRow <= nEndRow && !bStop)
+ {
+ SCROW nHeightEndRow;
+ USHORT nHeight = pTable->GetRowHeight( nRow, NULL, &nHeightEndRow);
+ if (nHeightEndRow > nEndRow)
+ nHeightEndRow = nEndRow;
+ if (!nHeight)
+ nRow = nHeightEndRow + 1;
+ else
+ {
+ SCROW nRows = nHeightEndRow - nRow + 1;
+ sal_Int64 nAdd = static_cast<sal_Int64>(nHeight) * nRows;
+ if (nAdd + rTwips >= nStopTwips)
+ {
+ sal_Int64 nDiff = nAdd + rTwips - nStopTwips;
+ nRows -= static_cast<SCROW>(nDiff / nHeight);
+ nAdd = nHeight * nRows;
+ // We're looking for a value that satisfies loop condition.
+ if (nAdd + rTwips >= nStopTwips)
+ {
+ --nRows;
+ nAdd -= nHeight;
+ }
+ bStop = true;
+ }
+ rTwips += static_cast<long>(nAdd);
+ nRow += nRows;
+ }
+ }
+ if (nRow > rPosY)
+ {
+ --nRow;
+ bAdded = true;
+ }
+ rPosY = nRow;
+ return bAdded;
+}
+
+ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect )
+{
+ ScTable* pTable = pTab[nTab];
+ if (!pTable)
+ {
+ DBG_ERROR("GetRange ohne Tabelle");
+ return ScRange();
+ }
+
+ Rectangle aPosRect = rMMRect;
+ if ( IsNegativePage( nTab ) )
+ ScDrawLayer::MirrorRectRTL( aPosRect ); // always with positive (LTR) values
+
+ long nSize;
+ long nTwips;
+ long nAdd;
+ BOOL bEnd;
+
+ nSize = 0;
+ nTwips = (long) (aPosRect.Left() / HMM_PER_TWIPS);
+
+ SCCOL nX1 = 0;
+ bEnd = FALSE;
+ while (!bEnd)
+ {
+ nAdd = (long) pTable->GetColWidth(nX1);
+ if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL)
+ {
+ nSize += nAdd;
+ ++nX1;
+ }
+ else
+ bEnd = TRUE;
+ }
+
+ nTwips = (long) (aPosRect.Right() / HMM_PER_TWIPS);
+
+ SCCOL nX2 = nX1;
+ bEnd = FALSE;
+ while (!bEnd)
+ {
+ nAdd = (long) pTable->GetColWidth(nX2);
+ if (nSize+nAdd < nTwips && nX2<MAXCOL)
+ {
+ nSize += nAdd;
+ ++nX2;
+ }
+ else
+ bEnd = TRUE;
+ }
+
+
+ nSize = 0;
+ nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS);
+
+ SCROW nY1 = 0;
+ // Was if(nSize+nAdd<=nTwips+1) inside loop => if(nSize+nAdd<nTwips+2)
+ if (lcl_AddTwipsWhile( nSize, nTwips+2, nY1, MAXROW, pTable) && nY1 < MAXROW)
+ ++nY1; // original loop ended on last matched +1 unless that was MAXROW
+
+ nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS);
+
+ SCROW nY2 = nY1;
+ // Was if(nSize+nAdd<nTwips) inside loop => if(nSize+nAdd<nTwips)
+ if (lcl_AddTwipsWhile( nSize, nTwips, nY2, MAXROW, pTable) && nY2 < MAXROW)
+ ++nY2; // original loop ended on last matched +1 unless that was MAXROW
+
+ return ScRange( nX1,nY1,nTab, nX2,nY2,nTab );
+}
+
+void ScDocument::SetEmbedded( const Rectangle& rRect ) // aus VisArea (1/100 mm)
+{
+ bIsEmbedded = TRUE;
+ aEmbedRange = GetRange( nVisibleTab, rRect );
+}
+
+// VisArea auf Zellgrenzen anpassen
+
+void lcl_SnapHor( ScTable* pTable, long& rVal, SCCOL& rStartCol )
+{
+ SCCOL nCol = 0;
+ long nTwips = (long) (rVal / HMM_PER_TWIPS);
+ long nSnap = 0;
+ while ( nCol<MAXCOL )
+ {
+ long nAdd = pTable->GetColWidth(nCol);
+ if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol )
+ {
+ nSnap += nAdd;
+ ++nCol;
+ }
+ else
+ break;
+ }
+ rVal = (long) ( nSnap * HMM_PER_TWIPS );
+ rStartCol = nCol;
+}
+
+void lcl_SnapVer( ScTable* pTable, long& rVal, SCROW& rStartRow )
+{
+ SCROW nRow = 0;
+ long nTwips = (long) (rVal / HMM_PER_TWIPS);
+ long nSnap = 0;
+
+ bool bFound = false;
+ for (SCROW i = nRow; i <= MAXROW; ++i)
+ {
+ SCROW nLastRow;
+ if (pTable->RowHidden(i, NULL, &nLastRow))
+ {
+ i = nLastRow;
+ continue;
+ }
+
+ nRow = i;
+ long nAdd = pTable->GetRowHeight(i);
+ if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow )
+ {
+ nSnap += nAdd;
+ ++nRow;
+ }
+ else
+ {
+ bFound = true;
+ break;
+ }
+ }
+ if (!bFound)
+ nRow = MAXROW; // all hidden down to the bottom
+
+ rVal = (long) ( nSnap * HMM_PER_TWIPS );
+ rStartRow = nRow;
+}
+
+void ScDocument::SnapVisArea( Rectangle& rRect ) const
+{
+ ScTable* pTable = pTab[nVisibleTab];
+ if (!pTable)
+ {
+ DBG_ERROR("SetEmbedded ohne Tabelle");
+ return;
+ }
+
+ BOOL bNegativePage = IsNegativePage( nVisibleTab );
+ if ( bNegativePage )
+ ScDrawLayer::MirrorRectRTL( rRect ); // calculate with positive (LTR) values
+
+ SCCOL nCol = 0;
+ lcl_SnapHor( pTable, rRect.Left(), nCol );
+ ++nCol; // mindestens eine Spalte
+ lcl_SnapHor( pTable, rRect.Right(), nCol );
+
+ SCROW nRow = 0;
+ lcl_SnapVer( pTable, rRect.Top(), nRow );
+ ++nRow; // mindestens eine Zeile
+ lcl_SnapVer( pTable, rRect.Bottom(), nRow );
+
+ if ( bNegativePage )
+ ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle
+}
+
+ScDocProtection* ScDocument::GetDocProtection() const
+{
+ return pDocProtection.get();
+}
+
+void ScDocument::SetDocProtection(const ScDocProtection* pProtect)
+{
+ if (pProtect)
+ pDocProtection.reset(new ScDocProtection(*pProtect));
+ else
+ pDocProtection.reset(NULL);
+}
+
+BOOL ScDocument::IsDocProtected() const
+{
+ return pDocProtection.get() && pDocProtection->isProtected();
+}
+
+BOOL ScDocument::IsDocEditable() const
+{
+ // import into read-only document is possible
+ return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
+}
+
+BOOL ScDocument::IsTabProtected( SCTAB nTab ) const
+{
+ if (VALIDTAB(nTab) && pTab[nTab])
+ return pTab[nTab]->IsProtected();
+
+ DBG_ERROR("Falsche Tabellennummer");
+ return FALSE;
+}
+
+ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const
+{
+ if (VALIDTAB(nTab) && pTab[nTab])
+ return pTab[nTab]->GetProtection();
+
+ return NULL;
+}
+
+void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect)
+{
+ if (!ValidTab(nTab))
+ return;
+
+ pTab[nTab]->SetProtection(pProtect);
+}
+
+void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest)
+{
+ if (!ValidTab(nTabSrc) || !ValidTab(nTabDest))
+ return;
+
+ pTab[nTabDest]->SetProtection( pTab[nTabSrc]->GetProtection() );
+}
+
+const ScDocOptions& ScDocument::GetDocOptions() const
+{
+ DBG_ASSERT( pDocOptions, "No DocOptions! :-(" );
+ return *pDocOptions;
+}
+
+void ScDocument::SetDocOptions( const ScDocOptions& rOpt )
+{
+ DBG_ASSERT( pDocOptions, "No DocOptions! :-(" );
+ *pDocOptions = rOpt;
+
+ xPoolHelper->SetFormTableOpt(rOpt);
+}
+
+const ScViewOptions& ScDocument::GetViewOptions() const
+{
+ DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
+ return *pViewOptions;
+}
+
+void ScDocument::SetViewOptions( const ScViewOptions& rOpt )
+{
+ DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
+ *pViewOptions = rOpt;
+}
+
+void ScDocument::GetLanguage( LanguageType& rLatin, LanguageType& rCjk, LanguageType& rCtl ) const
+{
+ rLatin = eLanguage;
+ rCjk = eCjkLanguage;
+ rCtl = eCtlLanguage;
+}
+
+void ScDocument::SetLanguage( LanguageType eLatin, LanguageType eCjk, LanguageType eCtl )
+{
+ eLanguage = eLatin;
+ eCjkLanguage = eCjk;
+ eCtlLanguage = eCtl;
+ if ( xPoolHelper.isValid() )
+ {
+ ScDocumentPool* pPool = xPoolHelper->GetDocPool();
+ pPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) );
+ pPool->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage, ATTR_CJK_FONT_LANGUAGE ) );
+ pPool->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage, ATTR_CTL_FONT_LANGUAGE ) );
+ }
+
+ UpdateDrawLanguages(); // set edit engine defaults in drawing layer pool
+}
+
+void ScDocument::SetDrawDefaults()
+{
+ bSetDrawDefaults = TRUE;
+ UpdateDrawDefaults();
+}
+
+Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow,
+ SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
+{
+ if (!ValidTab(nTab) || !pTab[nTab])
+ {
+ DBG_ERROR("GetMMRect: falsche Tabelle");
+ return Rectangle(0,0,0,0);
+ }
+
+ SCCOL i;
+ Rectangle aRect;
+
+ for (i=0; i<nStartCol; i++)
+ aRect.Left() += GetColWidth(i,nTab);
+ aRect.Top() += GetRowHeight( 0, nStartRow-1, nTab);
+
+ aRect.Right() = aRect.Left();
+ aRect.Bottom() = aRect.Top();
+
+ for (i=nStartCol; i<=nEndCol; i++)
+ aRect.Right() += GetColWidth(i,nTab);
+ aRect.Bottom() += GetRowHeight( nStartRow, nEndRow, nTab);
+
+ aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS);
+ aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS);
+ aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS);
+ aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS);
+
+ if ( IsNegativePage( nTab ) )
+ ScDrawLayer::MirrorRectRTL( aRect );
+
+ return aRect;
+}
+
+void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions )
+{
+ delete pExtDocOptions;
+ pExtDocOptions = pNewOptions;
+}
+
+void ScDocument::DoMergeContents( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
+ SCCOL nEndCol, SCROW nEndRow )
+{
+ String aEmpty;
+ String aTotal;
+ String aCellStr;
+ SCCOL nCol;
+ SCROW nRow;
+ for (nRow=nStartRow; nRow<=nEndRow; nRow++)
+ for (nCol=nStartCol; nCol<=nEndCol; nCol++)
+ {
+ GetString(nCol,nRow,nTab,aCellStr);
+ if (aCellStr.Len())
+ {
+ if (aTotal.Len())
+ aTotal += ' ';
+ aTotal += aCellStr;
+ }
+ if (nCol != nStartCol || nRow != nStartRow)
+ SetString(nCol,nRow,nTab,aEmpty);
+ }
+
+ SetString(nStartCol,nStartRow,nTab,aTotal);
+}
+
+void ScDocument::DoMerge( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
+ SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions )
+{
+ ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 );
+ ApplyAttr( nStartCol, nStartRow, nTab, aAttr );
+
+ if ( nEndCol > nStartCol )
+ ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR );
+ if ( nEndRow > nStartRow )
+ ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER );
+ if ( nEndCol > nStartCol && nEndRow > nStartRow )
+ ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
+
+ // remove all covered notes (removed captions are collected by drawing undo if active)
+ USHORT nDelFlag = IDF_NOTE | (bDeleteCaptions ? 0 : IDF_NOCAPTIONS);
+ if( nStartCol < nEndCol )
+ DeleteAreaTab( nStartCol + 1, nStartRow, nEndCol, nStartRow, nTab, nDelFlag );
+ if( nStartRow < nEndRow )
+ DeleteAreaTab( nStartCol, nStartRow + 1, nEndCol, nEndRow, nTab, nDelFlag );
+}
+
+void ScDocument::RemoveMerge( SCCOL nCol, SCROW nRow, SCTAB nTab )
+{
+ const ScMergeAttr* pAttr = (const ScMergeAttr*)
+ GetAttr( nCol, nRow, nTab, ATTR_MERGE );
+
+ if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 )
+ return;
+
+ SCCOL nEndCol = nCol + pAttr->GetColMerge() - 1;
+ SCROW nEndRow = nRow + pAttr->GetRowMerge() - 1;
+
+ RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
+
+ const ScMergeAttr* pDefAttr = (const ScMergeAttr*)
+ &xPoolHelper->GetDocPool()->GetDefaultItem( ATTR_MERGE );
+ ApplyAttr( nCol, nRow, nTab, *pDefAttr );
+}
+
+void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab,
+ SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow )
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ pTab[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow );
+}
+
+void ScDocument::IncSizeRecalcLevel( SCTAB nTab )
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ pTab[nTab]->IncRecalcLevel();
+}
+
+void ScDocument::DecSizeRecalcLevel( SCTAB nTab, bool bUpdateNoteCaptionPos )
+{
+ if ( ValidTab(nTab) && pTab[nTab] )
+ pTab[nTab]->DecRecalcLevel( bUpdateNoteCaptionPos );
+}
+
+// Wang Xu Ming -- 2009-8-17
+// DataPilot Migration - Cache&&Performance
+ScDPTableDataCache* ScDocument::GetDPObjectCache( long nID )
+{
+ for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ )
+ { //
+ if ( nID == (*iter)->GetId() )
+ return *iter;
+ }
+ return NULL;
+}
+
+ScDPTableDataCache* ScDocument::GetUsedDPObjectCache ( ScRange rRange )
+{
+ ScDPTableDataCache* pCache = NULL;
+ USHORT nCount = GetDPCollection()->GetCount();
+ for ( short i=nCount-1; i>=0 ; i--)
+ {
+ if ( const ScSheetSourceDesc* pUsedSheetDesc = (*pDPCollection)[i]->GetSheetDesc() )
+ if ( rRange == pUsedSheetDesc->aSourceRange )
+ {
+ long nID = (*pDPCollection)[i]->GetCacheId();
+ if ( nID >= 0 )
+ pCache= GetDPObjectCache( nID );
+ if ( pCache )
+ return pCache;
+ }
+ }
+ return pCache;
+}
+
+long ScDocument::AddDPObjectCache( ScDPTableDataCache* pData )
+{
+ if ( pData->GetId() < 0 )
+ { //create a id for it
+ pData->SetId( GetNewDPObjectCacheId() );
+ }
+ m_listDPObjectsCaches.push_back( pData );
+ return pData->GetId();
+}
+
+long ScDocument::GetNewDPObjectCacheId()
+{
+ long nID = 0;
+
+ bool bFound = false;
+ std::list<ScDPTableDataCache*>::iterator iter;
+ do {
+ for ( iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ )
+ { //Get a new Id
+ if ( nID == (*iter)->GetId() )
+ {
+ nID++;
+ bFound = true;
+ break;
+ }
+ }
+ if ( iter == m_listDPObjectsCaches.end() )
+ bFound = false;
+ } while ( bFound );
+
+ return nID;
+}
+
+void ScDocument::RemoveDPObjectCache( long nID )
+{
+ for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ )
+ {
+ if ( nID == (*iter)->GetId() )
+ {
+ ScDPTableDataCache* pCache = *iter;
+ m_listDPObjectsCaches.erase( iter );
+ delete pCache;
+ break;
+ }
+ }
+
+}
+
+void ScDocument::RemoveUnusedDPObjectCaches()
+{
+ for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ )
+ {
+ long nID = (*iter)->GetId();
+ USHORT nCount = GetDPCollection()->GetCount();
+ USHORT i ;
+ for ( i=0; i<nCount; i++)
+ {
+ if ( nID == (*pDPCollection)[i]->GetCacheId() )
+ break;
+ }
+ if ( i == nCount )
+ {
+ ScDPTableDataCache* pCache = *iter;
+ m_listDPObjectsCaches.erase( iter );
+ delete pCache;
+ continue;
+ }
+ }
+}
+
+void ScDocument::GetUsedDPObjectCache( std::list<ScDPTableDataCache*>& usedlist )
+{
+ for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ )
+ {
+ long nID = (*iter)->GetId();
+ USHORT nCount = GetDPCollection()->GetCount();
+ USHORT i=0;
+ for ( i=0; i<nCount; i++)
+ if ( nID == (*pDPCollection)[i]->GetCacheId() )
+ break;
+ if ( i != nCount )
+ usedlist.push_back( *iter );
+ }
+}
+// End Comments