update dev300-m57
[ooovba.git] / sc / source / core / data / documen3.cxx
blob263619b1b1e1359f1f67ea5bf37c90f6e2485def
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: documen3.cxx,v $
10 * $Revision: 1.42.100.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #include "scitems.hxx"
37 #include <svx/langitem.hxx>
38 #include <svx/srchitem.hxx>
39 #include <svx/linkmgr.hxx>
40 #include <sfx2/bindings.hxx>
41 #include <sfx2/objsh.hxx>
42 #include <svtools/zforlist.hxx>
43 #include <svtools/PasswordHelper.hxx>
44 #include <vcl/svapp.hxx>
45 #include "document.hxx"
46 #include "attrib.hxx"
47 #include "cell.hxx"
48 #include "table.hxx"
49 #include "rangenam.hxx"
50 #include "dbcolect.hxx"
51 #include "pivot.hxx"
52 #include "docpool.hxx"
53 #include "poolhelp.hxx"
54 #include "autoform.hxx"
55 #include "rangelst.hxx"
56 #include "chartarr.hxx"
57 #include "chartlock.hxx"
58 #include "compiler.hxx"
59 #include "refupdat.hxx"
60 #include "docoptio.hxx"
61 #include "viewopti.hxx"
62 #include "scextopt.hxx"
63 #include "brdcst.hxx"
64 #include "bcaslot.hxx"
65 #include "tablink.hxx"
66 #include "externalrefmgr.hxx"
67 #include "markdata.hxx"
68 #include "validat.hxx"
69 #include "dociter.hxx"
70 #include "detdata.hxx"
71 #include "detfunc.hxx"
72 #include "scmod.hxx" // SC_MOD
73 #include "inputopt.hxx" // GetExpandRefs
74 #include "chartlis.hxx"
75 #include "sc.hrc" // SID_LINK
76 #include "hints.hxx"
77 #include "dpobject.hxx"
78 #include "unoguard.hxx"
79 #include "drwlayer.hxx"
80 #include "unoreflist.hxx"
81 #include "listenercalls.hxx"
82 #include "tabprotection.hxx"
83 #include "clipparam.hxx"
84 #include "formulaparserpool.hxx"
86 #include <memory>
88 using namespace com::sun::star;
89 using ::std::auto_ptr;
91 //------------------------------------------------------------------------
93 ScRangeName* ScDocument::GetRangeName()
95 return pRangeName;
98 void ScDocument::SetRangeName( ScRangeName* pNewRangeName )
100 if (pRangeName)
101 delete pRangeName;
102 pRangeName = pNewRangeName;
105 //UNUSED2008-05 ScRangeData* ScDocument::GetRangeAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab,
106 //UNUSED2008-05 BOOL bStartOnly) const
107 //UNUSED2008-05 {
108 //UNUSED2008-05 if ( pRangeName )
109 //UNUSED2008-05 return pRangeName->GetRangeAtCursor( ScAddress( nCol, nRow, nTab ), bStartOnly );
110 //UNUSED2008-05 else
111 //UNUSED2008-05 return NULL;
112 //UNUSED2008-05 }
114 ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, String* pName ) const
116 ScRangeData* pData = NULL;
117 if ( pRangeName )
119 pData = pRangeName->GetRangeAtBlock( rBlock );
120 if (pData && pName)
121 *pName = pData->GetName();
123 return pData;
126 ScDBCollection* ScDocument::GetDBCollection() const
128 return pDBCollection;
131 void ScDocument::SetDBCollection( ScDBCollection* pNewDBCollection, BOOL bRemoveAutoFilter )
133 if ( bRemoveAutoFilter )
135 // remove auto filter attribute if new db data don't contain auto filter flag
136 // start position is also compared, so bRemoveAutoFilter must not be set from ref-undo!
138 if ( pDBCollection )
140 USHORT nOldCount = pDBCollection->GetCount();
141 for (USHORT nOld=0; nOld<nOldCount; nOld++)
143 ScDBData* pOldData = (*pDBCollection)[nOld];
144 if ( pOldData->HasAutoFilter() )
146 ScRange aOldRange;
147 pOldData->GetArea( aOldRange );
149 BOOL bFound = FALSE;
150 USHORT nNewIndex = 0;
151 if ( pNewDBCollection &&
152 pNewDBCollection->SearchName( pOldData->GetName(), nNewIndex ) )
154 ScDBData* pNewData = (*pNewDBCollection)[nNewIndex];
155 if ( pNewData->HasAutoFilter() )
157 ScRange aNewRange;
158 pNewData->GetArea( aNewRange );
159 if ( aOldRange.aStart == aNewRange.aStart )
160 bFound = TRUE;
164 if ( !bFound )
166 aOldRange.aEnd.SetRow( aOldRange.aStart.Row() );
167 RemoveFlagsTab( aOldRange.aStart.Col(), aOldRange.aStart.Row(),
168 aOldRange.aEnd.Col(), aOldRange.aEnd.Row(),
169 aOldRange.aStart.Tab(), SC_MF_AUTO );
170 if (pShell)
171 pShell->Broadcast( ScPaintHint( aOldRange, PAINT_GRID ) );
178 if (pDBCollection)
179 delete pDBCollection;
180 pDBCollection = pNewDBCollection;
183 ScDBData* ScDocument::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, BOOL bStartOnly) const
185 if (pDBCollection)
186 return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly);
187 else
188 return NULL;
191 ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
193 if (pDBCollection)
194 return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2);
195 else
196 return NULL;
199 ScDPCollection* ScDocument::GetDPCollection()
201 if (!pDPCollection)
202 pDPCollection = new ScDPCollection(this);
203 return pDPCollection;
206 ScDPObject* ScDocument::GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
208 if (!pDPCollection)
209 return NULL;
211 USHORT nCount = pDPCollection->GetCount();
212 ScAddress aPos( nCol, nRow, nTab );
213 for (USHORT i=0; i<nCount; i++)
214 if ( (*pDPCollection)[i]->GetOutRange().In( aPos ) )
215 return (*pDPCollection)[i];
217 return NULL;
220 ScDPObject* ScDocument::GetDPAtBlock( const ScRange & rBlock ) const
222 if (!pDPCollection)
223 return NULL;
225 /* Walk the collection in reverse order to get something of an
226 * approximation of MS Excels 'most recent' effect. */
227 USHORT i = pDPCollection->GetCount();
228 while ( i-- > 0 )
229 if ( (*pDPCollection)[i]->GetOutRange().In( rBlock ) )
230 return (*pDPCollection)[i];
232 return NULL;
235 ScChartCollection* ScDocument::GetChartCollection() const
237 return pChartCollection;
240 void ScDocument::StopTemporaryChartLock()
242 if( apTemporaryChartLock.get() )
243 apTemporaryChartLock->StopLocking();
246 void ScDocument::SetChartListenerCollection(
247 ScChartListenerCollection* pNewChartListenerCollection,
248 BOOL bSetChartRangeLists )
250 ScChartListenerCollection* pOld = pChartListenerCollection;
251 pChartListenerCollection = pNewChartListenerCollection;
252 if ( pChartListenerCollection )
254 if ( pOld )
255 pChartListenerCollection->SetDiffDirty( *pOld, bSetChartRangeLists );
256 pChartListenerCollection->StartAllListeners();
258 delete pOld;
261 void ScDocument::SetScenario( SCTAB nTab, BOOL bFlag )
263 if (ValidTab(nTab) && pTab[nTab])
264 pTab[nTab]->SetScenario(bFlag);
267 BOOL ScDocument::IsScenario( SCTAB nTab ) const
269 return ValidTab(nTab) && pTab[nTab] &&pTab[nTab]->IsScenario();
270 //if (ValidTab(nTab) && pTab[nTab])
271 // return pTab[nTab]->IsScenario();
273 //return FALSE;
276 void ScDocument::SetScenarioData( SCTAB nTab, const String& rComment,
277 const Color& rColor, USHORT nFlags )
279 if (ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsScenario())
281 pTab[nTab]->SetScenarioComment( rComment );
282 pTab[nTab]->SetScenarioColor( rColor );
283 pTab[nTab]->SetScenarioFlags( nFlags );
287 void ScDocument::GetScenarioData( SCTAB nTab, String& rComment,
288 Color& rColor, USHORT& rFlags ) const
290 if (ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsScenario())
292 pTab[nTab]->GetScenarioComment( rComment );
293 rColor = pTab[nTab]->GetScenarioColor();
294 rFlags = pTab[nTab]->GetScenarioFlags();
298 void ScDocument::GetScenarioFlags( SCTAB nTab, USHORT& rFlags ) const
300 if (VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->IsScenario())
301 rFlags = pTab[nTab]->GetScenarioFlags();
304 BOOL ScDocument::IsLinked( SCTAB nTab ) const
306 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsLinked();
307 // euqivalent to
308 //if (ValidTab(nTab) && pTab[nTab])
309 // return pTab[nTab]->IsLinked();
310 //return FALSE;
313 formula::FormulaGrammar::AddressConvention ScDocument::GetAddressConvention() const
315 return formula::FormulaGrammar::extractRefConvention(eGrammar);
318 formula::FormulaGrammar::Grammar ScDocument::GetGrammar() const
320 return eGrammar;
323 void ScDocument::SetGrammar( formula::FormulaGrammar::Grammar eGram )
325 eGrammar = eGram;
328 BOOL ScDocument::GetLinkMode( SCTAB nTab ) const
330 if (ValidTab(nTab) && pTab[nTab])
331 return pTab[nTab]->GetLinkMode();
332 return SC_LINK_NONE;
335 const String& ScDocument::GetLinkDoc( SCTAB nTab ) const
337 if (ValidTab(nTab) && pTab[nTab])
338 return pTab[nTab]->GetLinkDoc();
339 return EMPTY_STRING;
342 const String& ScDocument::GetLinkFlt( SCTAB nTab ) const
344 if (ValidTab(nTab) && pTab[nTab])
345 return pTab[nTab]->GetLinkFlt();
346 return EMPTY_STRING;
349 const String& ScDocument::GetLinkOpt( SCTAB nTab ) const
351 if (ValidTab(nTab) && pTab[nTab])
352 return pTab[nTab]->GetLinkOpt();
353 return EMPTY_STRING;
356 const String& ScDocument::GetLinkTab( SCTAB nTab ) const
358 if (ValidTab(nTab) && pTab[nTab])
359 return pTab[nTab]->GetLinkTab();
360 return EMPTY_STRING;
363 ULONG ScDocument::GetLinkRefreshDelay( SCTAB nTab ) const
365 if (ValidTab(nTab) && pTab[nTab])
366 return pTab[nTab]->GetLinkRefreshDelay();
367 return 0;
370 void ScDocument::SetLink( SCTAB nTab, BYTE nMode, const String& rDoc,
371 const String& rFilter, const String& rOptions,
372 const String& rTabName, ULONG nRefreshDelay )
374 if (ValidTab(nTab) && pTab[nTab])
375 pTab[nTab]->SetLink( nMode, rDoc, rFilter, rOptions, rTabName, nRefreshDelay );
378 BOOL ScDocument::HasLink( const String& rDoc,
379 const String& rFilter, const String& rOptions ) const
381 SCTAB nCount = GetTableCount();
382 for (SCTAB i=0; i<nCount; i++)
383 if (pTab[i]->IsLinked()
384 && pTab[i]->GetLinkDoc() == rDoc
385 && pTab[i]->GetLinkFlt() == rFilter
386 && pTab[i]->GetLinkOpt() == rOptions)
387 return TRUE;
389 return FALSE;
392 BOOL ScDocument::LinkExternalTab( SCTAB& rTab, const String& aDocTab,
393 const String& aFileName, const String& aTabName )
395 if ( IsClipboard() )
397 DBG_ERRORFILE( "LinkExternalTab in Clipboard" );
398 return FALSE;
400 rTab = 0;
401 String aFilterName; // wird vom Loader gefuellt
402 String aOptions; // Filter-Optionen
403 sal_uInt32 nLinkCnt = pExtDocOptions ? pExtDocOptions->GetDocSettings().mnLinkCnt : 0;
404 ScDocumentLoader aLoader( aFileName, aFilterName, aOptions, nLinkCnt + 1 );
405 if ( aLoader.IsError() )
406 return FALSE;
407 ScDocument* pSrcDoc = aLoader.GetDocument();
409 // Tabelle kopieren
410 SCTAB nSrcTab;
411 if ( pSrcDoc->GetTable( aTabName, nSrcTab ) )
413 if ( !InsertTab( SC_TAB_APPEND, aDocTab, TRUE ) )
415 DBG_ERRORFILE("can't insert external document table");
416 return FALSE;
418 rTab = GetTableCount() - 1;
419 // nicht neu einfuegen, nur Ergebnisse
420 TransferTab( pSrcDoc, nSrcTab, rTab, FALSE, TRUE );
422 else
423 return FALSE;
425 ULONG nRefreshDelay = 0;
427 BOOL bWasThere = HasLink( aFileName, aFilterName, aOptions );
428 SetLink( rTab, SC_LINK_VALUE, aFileName, aFilterName, aOptions, aTabName, nRefreshDelay );
429 if ( !bWasThere ) // Link pro Quelldokument nur einmal eintragen
431 ScTableLink* pLink = new ScTableLink( pShell, aFileName, aFilterName, aOptions, nRefreshDelay );
432 pLink->SetInCreate( TRUE );
433 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName,
434 &aFilterName );
435 pLink->Update();
436 pLink->SetInCreate( FALSE );
437 SfxBindings* pBindings = GetViewBindings();
438 if (pBindings)
439 pBindings->Invalidate( SID_LINKS );
441 return TRUE;
444 ScExternalRefManager* ScDocument::GetExternalRefManager()
446 if (!pExternalRefMgr.get())
447 pExternalRefMgr.reset(new ScExternalRefManager(this));
449 return pExternalRefMgr.get();
452 bool ScDocument::IsInExternalReferenceMarking() const
454 return pExternalRefMgr.get() && pExternalRefMgr->isInReferenceMarking();
457 void ScDocument::MarkUsedExternalReferences()
459 if (!pExternalRefMgr.get())
460 return;
461 if (!pExternalRefMgr->hasExternalData())
462 return;
463 // Charts.
464 bool bAllMarked = pExternalRefMgr->markUsedByLinkListeners();
465 // Formula cells.
466 for (SCTAB nTab = 0; !bAllMarked && nTab < nMaxTableNumber; ++nTab)
468 if (pTab[nTab])
469 bAllMarked = pTab[nTab]->MarkUsedExternalReferences();
471 /* NOTE: Conditional formats and validation objects are marked when
472 * collecting them during export. */
475 ScFormulaParserPool& ScDocument::GetFormulaParserPool() const
477 if( !mxFormulaParserPool.get() )
478 mxFormulaParserPool.reset( new ScFormulaParserPool( *this ) );
479 return *mxFormulaParserPool;
482 ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, BOOL bCreate )
484 ScOutlineTable* pVal = NULL;
486 if (VALIDTAB(nTab))
487 if (pTab[nTab])
489 pVal = pTab[nTab]->GetOutlineTable();
490 if (!pVal)
491 if (bCreate)
493 pTab[nTab]->StartOutlineTable();
494 pVal = pTab[nTab]->GetOutlineTable();
498 return pVal;
501 BOOL ScDocument::SetOutlineTable( SCTAB nTab, const ScOutlineTable* pNewOutline )
503 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->SetOutlineTable(pNewOutline);
504 //if (VALIDTAB(nTab))
505 // if (pTab[nTab])
506 // return pTab[nTab]->SetOutlineTable(pNewOutline);
508 //return FALSE;
511 void ScDocument::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow,
512 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
514 if (VALIDTAB(nTab) && pTab[nTab])
515 pTab[nTab]->DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
518 BOOL ScDocument::TestRemoveSubTotals( SCTAB nTab, const ScSubTotalParam& rParam )
520 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->TestRemoveSubTotals( rParam );
521 //if (VALIDTAB(nTab) && pTab[nTab] )
522 // return pTab[nTab]->TestRemoveSubTotals( rParam );
524 //return FALSE;
527 void ScDocument::RemoveSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
529 if ( VALIDTAB(nTab) && pTab[nTab] )
530 pTab[nTab]->RemoveSubTotals( rParam );
533 BOOL ScDocument::DoSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
535 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->DoSubTotals( rParam );
536 //if (VALIDTAB(nTab))
537 // if (pTab[nTab])
538 // return pTab[nTab]->DoSubTotals( rParam );
540 //return FALSE;
543 BOOL ScDocument::HasSubTotalCells( const ScRange& rRange )
545 ScCellIterator aIter( this, rRange );
546 ScBaseCell* pCell = aIter.GetFirst();
547 while (pCell)
549 if ( pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->IsSubTotal() )
550 return TRUE;
552 pCell = aIter.GetNext();
554 return FALSE; // none found
557 // kopiert aus diesem Dokument die Zellen von Positionen, an denen in pPosDoc
558 // auch Zellen stehen, nach pDestDoc
560 void ScDocument::CopyUpdated( ScDocument* pPosDoc, ScDocument* pDestDoc )
562 SCTAB nCount = GetTableCount();
563 for (SCTAB nTab=0; nTab<nCount; nTab++)
564 if (pTab[nTab] && pPosDoc->pTab[nTab] && pDestDoc->pTab[nTab])
565 pTab[nTab]->CopyUpdated( pPosDoc->pTab[nTab], pDestDoc->pTab[nTab] );
568 void ScDocument::CopyScenario( SCTAB nSrcTab, SCTAB nDestTab, BOOL bNewScenario )
570 if (ValidTab(nSrcTab) && ValidTab(nDestTab) && pTab[nSrcTab] && pTab[nDestTab])
572 // Flags fuer aktive Szenarios richtig setzen
573 // und aktuelle Werte in bisher aktive Szenarios zurueckschreiben
575 ScRangeList aRanges = *pTab[nSrcTab]->GetScenarioRanges();
576 const ULONG nRangeCount = aRanges.Count();
578 // nDestTab ist die Zieltabelle
579 for ( SCTAB nTab = nDestTab+1;
580 nTab<=MAXTAB && pTab[nTab] && pTab[nTab]->IsScenario();
581 nTab++ )
583 if ( pTab[nTab]->IsActiveScenario() ) // auch wenn's dasselbe Szenario ist
585 BOOL bTouched = FALSE;
586 for ( ULONG nR=0; nR<nRangeCount && !bTouched; nR++)
588 const ScRange* pRange = aRanges.GetObject(nR);
589 if ( pTab[nTab]->HasScenarioRange( *pRange ) )
590 bTouched = TRUE;
592 if (bTouched)
594 pTab[nTab]->SetActiveScenario(FALSE);
595 if ( pTab[nTab]->GetScenarioFlags() & SC_SCENARIO_TWOWAY )
596 pTab[nTab]->CopyScenarioFrom( pTab[nDestTab] );
601 pTab[nSrcTab]->SetActiveScenario(TRUE); // da kommt's her...
602 if (!bNewScenario) // Daten aus dem ausgewaehlten Szenario kopieren
604 BOOL bOldAutoCalc = GetAutoCalc();
605 SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
606 pTab[nSrcTab]->CopyScenarioTo( pTab[nDestTab] );
607 SetDirty();
608 SetAutoCalc( bOldAutoCalc );
613 void ScDocument::MarkScenario( SCTAB nSrcTab, SCTAB nDestTab, ScMarkData& rDestMark,
614 BOOL bResetMark, USHORT nNeededBits ) const
616 if (bResetMark)
617 rDestMark.ResetMark();
619 if (ValidTab(nSrcTab) && pTab[nSrcTab])
620 pTab[nSrcTab]->MarkScenarioIn( rDestMark, nNeededBits );
622 rDestMark.SetAreaTab( nDestTab );
625 BOOL ScDocument::HasScenarioRange( SCTAB nTab, const ScRange& rRange ) const
627 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->HasScenarioRange( rRange );
628 //if (ValidTab(nTab) && pTab[nTab])
629 // return pTab[nTab]->HasScenarioRange( rRange );
631 //return FALSE;
634 const ScRangeList* ScDocument::GetScenarioRanges( SCTAB nTab ) const
636 if (ValidTab(nTab) && pTab[nTab])
637 return pTab[nTab]->GetScenarioRanges();
639 return NULL;
642 BOOL ScDocument::IsActiveScenario( SCTAB nTab ) const
644 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsActiveScenario( );
645 //if (ValidTab(nTab) && pTab[nTab])
646 // return pTab[nTab]->IsActiveScenario();
648 //return FALSE;
651 void ScDocument::SetActiveScenario( SCTAB nTab, BOOL bActive )
653 if (ValidTab(nTab) && pTab[nTab])
654 pTab[nTab]->SetActiveScenario( bActive );
657 BOOL ScDocument::TestCopyScenario( SCTAB nSrcTab, SCTAB nDestTab ) const
659 if (ValidTab(nSrcTab) && ValidTab(nDestTab))
660 return pTab[nSrcTab]->TestCopyScenarioTo( pTab[nDestTab] );
662 DBG_ERROR("falsche Tabelle bei TestCopyScenario");
663 return FALSE;
666 void ScDocument::AddUnoObject( SfxListener& rObject )
668 if (!pUnoBroadcaster)
669 pUnoBroadcaster = new SfxBroadcaster;
671 rObject.StartListening( *pUnoBroadcaster );
674 void ScDocument::RemoveUnoObject( SfxListener& rObject )
676 if (pUnoBroadcaster)
678 rObject.EndListening( *pUnoBroadcaster );
680 if ( bInUnoBroadcast )
682 // #107294# Broadcasts from ScDocument::BroadcastUno are the only way that
683 // uno object methods are called without holding a reference.
685 // If RemoveUnoObject is called from an object dtor in the finalizer thread
686 // while the main thread is calling BroadcastUno, the dtor thread must wait
687 // (or the object's Notify might try to access a deleted object).
688 // The SolarMutex can't be locked here because if a component is called from
689 // a VCL event, the main thread has the SolarMutex locked all the time.
691 // This check is done after calling EndListening, so a later BroadcastUno call
692 // won't touch this object.
694 vos::IMutex& rSolarMutex = Application::GetSolarMutex();
695 if ( rSolarMutex.tryToAcquire() )
697 // BroadcastUno is always called with the SolarMutex locked, so if it
698 // can be acquired, this is within the same thread (should not happen)
699 DBG_ERRORFILE( "RemoveUnoObject called from BroadcastUno" );
700 rSolarMutex.release();
702 else
704 // let the thread that called BroadcastUno continue
705 while ( bInUnoBroadcast )
707 vos::OThread::yield();
712 else
714 DBG_ERROR("No Uno broadcaster");
718 void ScDocument::BroadcastUno( const SfxHint &rHint )
720 if (pUnoBroadcaster)
722 bInUnoBroadcast = TRUE;
723 pUnoBroadcaster->Broadcast( rHint );
724 bInUnoBroadcast = FALSE;
726 // During Broadcast notification, Uno objects can add to pUnoListenerCalls.
727 // The listener calls must be processed after completing the broadcast,
728 // because they can add or remove objects from pUnoBroadcaster.
730 if ( pUnoListenerCalls && rHint.ISA( SfxSimpleHint ) &&
731 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DATACHANGED &&
732 !bInUnoListenerCall )
734 // Listener calls may lead to BroadcastUno calls again. The listener calls
735 // are not nested, instead the calls are collected in the list, and the
736 // outermost call executes them all.
738 ScChartLockGuard aChartLockGuard(this);
739 bInUnoListenerCall = TRUE;
740 pUnoListenerCalls->ExecuteAndClear();
741 bInUnoListenerCall = FALSE;
746 void ScDocument::AddUnoListenerCall( const uno::Reference<util::XModifyListener>& rListener,
747 const lang::EventObject& rEvent )
749 DBG_ASSERT( bInUnoBroadcast, "AddUnoListenerCall is supposed to be called from BroadcastUno only" );
751 if ( !pUnoListenerCalls )
752 pUnoListenerCalls = new ScUnoListenerCalls;
753 pUnoListenerCalls->Add( rListener, rEvent );
756 void ScDocument::BeginUnoRefUndo()
758 DBG_ASSERT( !pUnoRefUndoList, "BeginUnoRefUndo twice" );
759 delete pUnoRefUndoList;
761 pUnoRefUndoList = new ScUnoRefList;
764 ScUnoRefList* ScDocument::EndUnoRefUndo()
766 ScUnoRefList* pRet = pUnoRefUndoList;
767 pUnoRefUndoList = NULL;
768 return pRet; // must be deleted by caller!
771 void ScDocument::AddUnoRefChange( sal_Int64 nId, const ScRangeList& rOldRanges )
773 if ( pUnoRefUndoList )
774 pUnoRefUndoList->Add( nId, rOldRanges );
777 sal_Int64 ScDocument::GetNewUnoId()
779 return ++nUnoObjectId;
782 void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode,
783 SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
784 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
785 SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
786 ScDocument* pUndoDoc, BOOL bIncludeDraw )
788 PutInOrder( nCol1, nCol2 );
789 PutInOrder( nRow1, nRow2 );
790 PutInOrder( nTab1, nTab2 );
791 if (VALIDTAB(nTab1) && VALIDTAB(nTab2))
793 BOOL bExpandRefsOld = IsExpandRefs();
794 if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
795 SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
796 SCTAB i;
797 SCTAB iMax;
798 if ( eUpdateRefMode == URM_COPY )
800 i = nTab1;
801 iMax = nTab2;
803 else
805 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
806 xColNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
807 xRowNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
808 pDBCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
809 pRangeName->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
810 if ( pDPCollection )
811 pDPCollection->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
812 UpdateChartRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
813 UpdateRefAreaLinks( eUpdateRefMode, aRange, nDx, nDy, nDz );
814 if ( pCondFormList )
815 pCondFormList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
816 if ( pValidationList )
817 pValidationList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
818 if ( pDetOpList )
819 pDetOpList->UpdateReference( this, eUpdateRefMode, aRange, nDx, nDy, nDz );
820 if ( pUnoBroadcaster )
821 pUnoBroadcaster->Broadcast( ScUpdateRefHint(
822 eUpdateRefMode, aRange, nDx, nDy, nDz ) );
823 i = 0;
824 iMax = MAXTAB;
826 for ( ; i<=iMax; i++)
827 if (pTab[i])
828 pTab[i]->UpdateReference(
829 eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
830 nDx, nDy, nDz, pUndoDoc, bIncludeDraw );
832 if ( bIsEmbedded )
834 SCCOL theCol1;
835 SCROW theRow1;
836 SCTAB theTab1;
837 SCCOL theCol2;
838 SCROW theRow2;
839 SCTAB theTab2;
840 theCol1 = aEmbedRange.aStart.Col();
841 theRow1 = aEmbedRange.aStart.Row();
842 theTab1 = aEmbedRange.aStart.Tab();
843 theCol2 = aEmbedRange.aEnd.Col();
844 theRow2 = aEmbedRange.aEnd.Row();
845 theTab2 = aEmbedRange.aEnd.Tab();
846 if ( ScRefUpdate::Update( this, eUpdateRefMode, nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
847 nDx,nDy,nDz, theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
849 aEmbedRange = ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
852 SetExpandRefs( bExpandRefsOld );
854 // #30428# after moving, no clipboard move ref-updates are possible
855 if ( eUpdateRefMode != URM_COPY && IsClipboardSource() )
857 ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
858 if (pClipDoc)
859 pClipDoc->GetClipParam().mbCutMode = false;
864 void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDoc,
865 const ScMarkData& rMark, ScDocument* pUndoDoc )
867 DBG_ASSERT(pClipDoc->bIsClip, "UpdateTranspose: kein Clip");
869 ScRange aSource;
870 ScClipParam& rClipParam = GetClipParam();
871 if (rClipParam.maRanges.Count())
872 aSource = *rClipParam.maRanges.First();
873 ScAddress aDest = rDestPos;
875 SCTAB nClipTab = 0;
876 for (SCTAB nDestTab=0; nDestTab<=MAXTAB && pTab[nDestTab]; nDestTab++)
877 if (rMark.GetTableSelect(nDestTab))
879 while (!pClipDoc->pTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
880 aSource.aStart.SetTab( nClipTab );
881 aSource.aEnd.SetTab( nClipTab );
882 aDest.SetTab( nDestTab );
884 // wie UpdateReference
886 pRangeName->UpdateTranspose( aSource, aDest ); // vor den Zellen!
887 for (SCTAB i=0; i<=MAXTAB; i++)
888 if (pTab[i])
889 pTab[i]->UpdateTranspose( aSource, aDest, pUndoDoc );
891 nClipTab = (nClipTab+1) % (MAXTAB+1);
895 void ScDocument::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
897 //! pDBCollection
898 //! pPivotCollection
899 //! UpdateChartRef
901 pRangeName->UpdateGrow( rArea, nGrowX, nGrowY );
903 for (SCTAB i=0; i<=MAXTAB && pTab[i]; i++)
904 pTab[i]->UpdateGrow( rArea, nGrowX, nGrowY );
907 void ScDocument::Fill(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
908 ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
909 double nStepValue, double nMaxValue)
911 PutInOrder( nCol1, nCol2 );
912 PutInOrder( nRow1, nRow2 );
913 for (SCTAB i=0; i <= MAXTAB; i++)
914 if (pTab[i])
915 if (rMark.GetTableSelect(i))
916 pTab[i]->Fill(nCol1, nRow1, nCol2, nRow2,
917 nFillCount, eFillDir, eFillCmd, eFillDateCmd,
918 nStepValue, nMaxValue);
921 String ScDocument::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
923 SCTAB nTab = rSource.aStart.Tab();
924 if (pTab[nTab])
925 return pTab[nTab]->GetAutoFillPreview( rSource, nEndX, nEndY );
927 return EMPTY_STRING;
930 void ScDocument::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
931 USHORT nFormatNo, const ScMarkData& rMark )
933 PutInOrder( nStartCol, nEndCol );
934 PutInOrder( nStartRow, nEndRow );
935 for (SCTAB i=0; i <= MAXTAB; i++)
936 if (pTab[i])
937 if (rMark.GetTableSelect(i))
938 pTab[i]->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo );
941 void ScDocument::GetAutoFormatData(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
942 ScAutoFormatData& rData)
944 if (VALIDTAB(nTab))
946 if (pTab[nTab])
948 PutInOrder(nStartCol, nEndCol);
949 PutInOrder(nStartRow, nEndRow);
950 pTab[nTab]->GetAutoFormatData(nStartCol, nStartRow, nEndCol, nEndRow, rData);
955 // static
956 void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem& rSearchItem,
957 SCCOL& rCol, SCROW& rRow )
959 USHORT nCommand = rSearchItem.GetCommand();
960 BOOL bReplace = ( nCommand == SVX_SEARCHCMD_REPLACE ||
961 nCommand == SVX_SEARCHCMD_REPLACE_ALL );
962 if ( rSearchItem.GetBackward() )
964 if ( rSearchItem.GetRowDirection() )
966 if ( rSearchItem.GetPattern() )
968 rCol = MAXCOL;
969 rRow = MAXROW+1;
971 else if ( bReplace )
973 rCol = MAXCOL;
974 rRow = MAXROW;
976 else
978 rCol = MAXCOL+1;
979 rRow = MAXROW;
982 else
984 if ( rSearchItem.GetPattern() )
986 rCol = MAXCOL+1;
987 rRow = MAXROW;
989 else if ( bReplace )
991 rCol = MAXCOL;
992 rRow = MAXROW;
994 else
996 rCol = MAXCOL;
997 rRow = MAXROW+1;
1001 else
1003 if ( rSearchItem.GetRowDirection() )
1005 if ( rSearchItem.GetPattern() )
1007 rCol = 0;
1008 rRow = (SCROW) -1;
1010 else if ( bReplace )
1012 rCol = 0;
1013 rRow = 0;
1015 else
1017 rCol = (SCCOL) -1;
1018 rRow = 0;
1021 else
1023 if ( rSearchItem.GetPattern() )
1025 rCol = (SCCOL) -1;
1026 rRow = 0;
1028 else if ( bReplace )
1030 rCol = 0;
1031 rRow = 0;
1033 else
1035 rCol = 0;
1036 rRow = (SCROW) -1;
1042 BOOL ScDocument::SearchAndReplace(const SvxSearchItem& rSearchItem,
1043 SCCOL& rCol, SCROW& rRow, SCTAB& rTab,
1044 ScMarkData& rMark,
1045 String& rUndoStr, ScDocument* pUndoDoc)
1047 //! getrennte Markierungen pro Tabelle verwalten !!!!!!!!!!!!!
1049 rMark.MarkToMulti();
1051 BOOL bFound = FALSE;
1052 if (VALIDTAB(rTab))
1054 SCCOL nCol;
1055 SCROW nRow;
1056 SCTAB nTab;
1057 USHORT nCommand = rSearchItem.GetCommand();
1058 if ( nCommand == SVX_SEARCHCMD_FIND_ALL ||
1059 nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1061 for (nTab = 0; nTab <= MAXTAB; nTab++)
1062 if (pTab[nTab])
1064 if (rMark.GetTableSelect(nTab))
1066 nCol = 0;
1067 nRow = 0;
1068 bFound |= pTab[nTab]->SearchAndReplace(
1069 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
1073 // Markierung wird innen schon komplett gesetzt
1075 else
1077 nCol = rCol;
1078 nRow = rRow;
1079 if (rSearchItem.GetBackward())
1081 for (nTab = rTab; ((SCsTAB)nTab >= 0) && !bFound; nTab--)
1082 if (pTab[nTab])
1084 if (rMark.GetTableSelect(nTab))
1086 bFound = pTab[nTab]->SearchAndReplace(
1087 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
1088 if (bFound)
1090 rCol = nCol;
1091 rRow = nRow;
1092 rTab = nTab;
1094 else
1095 ScDocument::GetSearchAndReplaceStart(
1096 rSearchItem, nCol, nRow );
1100 else
1102 for (nTab = rTab; (nTab <= MAXTAB) && !bFound; nTab++)
1103 if (pTab[nTab])
1105 if (rMark.GetTableSelect(nTab))
1107 bFound = pTab[nTab]->SearchAndReplace(
1108 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
1109 if (bFound)
1111 rCol = nCol;
1112 rRow = nRow;
1113 rTab = nTab;
1115 else
1116 ScDocument::GetSearchAndReplaceStart(
1117 rSearchItem, nCol, nRow );
1123 return bFound;
1126 BOOL ScDocument::IsFiltered( SCROW nRow, SCTAB nTab ) const
1128 if (VALIDTAB(nTab))
1129 if (pTab[nTab])
1130 return pTab[nTab]->IsFiltered( nRow );
1131 DBG_ERROR("Falsche Tabellennummer");
1132 return 0;
1135 // Outline anpassen
1137 BOOL ScDocument::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, BOOL bShow )
1139 if ( ValidTab(nTab) && pTab[nTab] )
1140 return pTab[nTab]->UpdateOutlineCol( nStartCol, nEndCol, bShow );
1142 DBG_ERROR("missing tab");
1143 return FALSE;
1146 BOOL ScDocument::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, BOOL bShow )
1148 if ( ValidTab(nTab) && pTab[nTab] )
1149 return pTab[nTab]->UpdateOutlineRow( nStartRow, nEndRow, bShow );
1151 DBG_ERROR("missing tab");
1152 return FALSE;
1155 void ScDocument::Sort(SCTAB nTab, const ScSortParam& rSortParam, BOOL bKeepQuery)
1157 if ( ValidTab(nTab) && pTab[nTab] )
1159 BOOL bOldDisableIdle = IsIdleDisabled();
1160 DisableIdle( TRUE );
1161 pTab[nTab]->Sort(rSortParam, bKeepQuery);
1162 DisableIdle( bOldDisableIdle );
1166 SCSIZE ScDocument::Query(SCTAB nTab, const ScQueryParam& rQueryParam, BOOL bKeepSub)
1168 if ( ValidTab(nTab) && pTab[nTab] )
1169 return pTab[nTab]->Query((ScQueryParam&)rQueryParam, bKeepSub);
1171 DBG_ERROR("missing tab");
1172 return 0;
1176 BOOL ScDocument::ValidQuery( SCROW nRow, SCTAB nTab, const ScQueryParam& rQueryParam, BOOL* pSpecial )
1178 if ( ValidTab(nTab) && pTab[nTab] )
1179 return pTab[nTab]->ValidQuery( nRow, rQueryParam, pSpecial );
1181 DBG_ERROR("missing tab");
1182 return FALSE;
1186 void ScDocument::GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, String& rStr)
1188 if ( ValidTab(nTab) && pTab[nTab] )
1189 pTab[nTab]->GetUpperCellString( nCol, nRow, rStr );
1190 else
1191 rStr.Erase();
1194 BOOL ScDocument::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, ScQueryParam& rQueryParam)
1196 if ( ValidTab(nTab) && pTab[nTab] )
1197 return pTab[nTab]->CreateQueryParam(nCol1, nRow1, nCol2, nRow2, rQueryParam);
1199 DBG_ERROR("missing tab");
1200 return FALSE;
1203 BOOL ScDocument::HasAutoFilter( SCCOL nCurCol, SCROW nCurRow, SCTAB nCurTab )
1205 ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab );
1206 BOOL bHasAutoFilter = ( pDBData != NULL );
1208 if ( pDBData )
1210 if ( pDBData->HasHeader() )
1212 SCCOL nCol;
1213 SCROW nRow;
1214 INT16 nFlag;
1216 ScQueryParam aParam;
1217 pDBData->GetQueryParam( aParam );
1218 nRow = aParam.nRow1;
1220 for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ )
1222 nFlag = ((ScMergeFlagAttr*)
1223 GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))->
1224 GetValue();
1226 if ( (nFlag & SC_MF_AUTO) == 0 )
1227 bHasAutoFilter = FALSE;
1230 else
1231 bHasAutoFilter = FALSE;
1234 return bHasAutoFilter;
1237 BOOL ScDocument::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1238 SCTAB nTab )
1240 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1241 //if (VALIDTAB(nTab))
1242 // if (pTab[nTab])
1243 // return pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1245 //return FALSE;
1248 BOOL ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1249 SCTAB nTab )
1251 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1252 //if (VALIDTAB(nTab))
1253 // if (pTab[nTab])
1254 // return pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1255 //return FALSE;
1258 void ScDocument::UpdateDynamicEndRow(ScDBData& rDBData) const
1260 SCCOL nCol1, nCol2;
1261 SCROW nRow1, nRow2;
1262 SCTAB nTab;
1263 rDBData.GetArea(nTab, nCol1, nRow1, nCol2, nRow2);
1264 SCCOL nCol1a = nCol1, nCol2a = nCol2;
1265 SCROW nRow1a = nRow1, nRow2a = nRow2;
1266 GetDataArea(nTab, nCol1a, nRow1a, nCol2a, nRow2a, false);
1267 rDBData.SetDynamicEndRow(nRow2a);
1271 // GetFilterEntries - Eintraege fuer AutoFilter-Listbox
1273 BOOL ScDocument::GetFilterEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedScStrCollection& rStrings, bool bFilter )
1275 if ( ValidTab(nTab) && pTab[nTab] && pDBCollection )
1277 ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, FALSE); //!??
1278 if (pDBData)
1280 UpdateDynamicEndRow(*pDBData);
1281 SCTAB nAreaTab;
1282 SCCOL nStartCol;
1283 SCROW nStartRow;
1284 SCCOL nEndCol;
1285 SCROW nEndRow;
1286 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1287 if (pDBData->HasHeader())
1288 ++nStartRow;
1290 ScQueryParam aParam;
1291 pDBData->GetQueryParam( aParam );
1292 nEndRow = aParam.nDynamicEndRow;
1293 rStrings.SetCaseSensitive( aParam.bCaseSens );
1295 // return all filter entries, if a filter condition is connected with a boolean OR
1296 if ( bFilter )
1298 SCSIZE nEntryCount = aParam.GetEntryCount();
1299 for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i )
1301 ScQueryEntry& rEntry = aParam.GetEntry(i);
1302 if ( rEntry.eConnect != SC_AND )
1304 bFilter = false;
1305 break;
1310 if ( bFilter )
1312 pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings );
1314 else
1316 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings );
1319 return TRUE;
1323 return FALSE;
1327 // GetFilterEntriesArea - Eintraege fuer Filter-Dialog
1330 BOOL ScDocument::GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow,
1331 SCTAB nTab, TypedScStrCollection& rStrings )
1333 if ( ValidTab(nTab) && pTab[nTab] )
1335 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings );
1336 return TRUE;
1339 return FALSE;
1343 // GetDataEntries - Eintraege fuer Auswahlliste-Listbox (keine Zahlen / Formeln)
1346 BOOL ScDocument::GetDataEntries( SCCOL nCol, SCROW nRow, SCTAB nTab,
1347 TypedScStrCollection& rStrings, BOOL bLimit )
1349 if( !bLimit )
1351 /* Try to generate the list from list validation. This part is skipped,
1352 if bLimit==TRUE, because in that case this function is called to get
1353 cell values for auto completion on input. */
1354 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
1355 if( nValidation )
1357 const ScValidationData* pData = GetValidationEntry( nValidation );
1358 if( pData && pData->FillSelectionList( rStrings, ScAddress( nCol, nRow, nTab ) ) )
1359 return TRUE;
1363 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
1364 //if (ValidTab(nTab) && pTab[nTab])
1365 // return pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
1367 //return FALSE;
1371 // GetFormulaEntries - Eintraege fuer Formel-AutoEingabe
1374 // Funktionen werden als 1 schon vom InputHandler eingefuegt
1375 #define SC_STRTYPE_NAMES 2
1376 #define SC_STRTYPE_DBNAMES 3
1377 #define SC_STRTYPE_HEADERS 4
1379 BOOL ScDocument::GetFormulaEntries( TypedScStrCollection& rStrings )
1381 USHORT i;
1384 // Bereichsnamen
1387 if ( pRangeName )
1389 USHORT nRangeCount = pRangeName->GetCount();
1390 for ( i=0; i<nRangeCount; i++ )
1392 ScRangeData* pData = (*pRangeName)[i];
1393 if (pData)
1395 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_NAMES );
1396 if ( !rStrings.Insert(pNew) )
1397 delete pNew;
1403 // Datenbank-Bereiche
1406 if ( pDBCollection )
1408 USHORT nDBCount = pDBCollection->GetCount();
1409 for ( i=0; i<nDBCount; i++ )
1411 ScDBData* pData = (*pDBCollection)[i];
1412 if (pData)
1414 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_DBNAMES );
1415 if ( !rStrings.Insert(pNew) )
1416 delete pNew;
1422 // Inhalte von Beschriftungsbereichen
1425 ScRangePairList* pLists[2];
1426 pLists[0] = GetColNameRanges();
1427 pLists[1] = GetRowNameRanges();
1428 for (USHORT nListNo=0; nListNo<2; nListNo++)
1430 ScRangePairList* pList = pLists[nListNo];
1431 if (pList)
1432 for ( ScRangePair* pPair = pList->First(); pPair; pPair = pList->Next() )
1434 ScRange aRange = pPair->GetRange(0);
1435 ScCellIterator aIter( this, aRange );
1436 for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() )
1437 if ( pCell->HasStringData() )
1439 String aStr = pCell->GetStringData();
1440 TypedStrData* pNew = new TypedStrData( aStr, 0.0, SC_STRTYPE_HEADERS );
1441 if ( !rStrings.Insert(pNew) )
1442 delete pNew;
1447 return TRUE;
1451 BOOL ScDocument::IsEmbedded() const
1453 return bIsEmbedded;
1456 void ScDocument::GetEmbedded( ScRange& rRange ) const
1458 rRange = aEmbedRange;
1461 Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm
1463 Rectangle aRect;
1464 ScTable* pTable = pTab[aEmbedRange.aStart.Tab()];
1465 if (!pTable)
1467 DBG_ERROR("GetEmbeddedRect ohne Tabelle");
1469 else
1471 SCCOL i;
1473 for (i=0; i<aEmbedRange.aStart.Col(); i++)
1474 aRect.Left() += pTable->GetColWidth(i);
1475 aRect.Top() += pTable->GetRowHeight( 0, aEmbedRange.aStart.Row() - 1);
1476 aRect.Right() = aRect.Left();
1477 for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++)
1478 aRect.Right() += pTable->GetColWidth(i);
1479 aRect.Bottom() = aRect.Top();
1480 aRect.Bottom() += pTable->GetRowHeight( aEmbedRange.aStart.Row(), aEmbedRange.aEnd.Row());
1482 aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS );
1483 aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS );
1484 aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS );
1485 aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS );
1487 return aRect;
1490 void ScDocument::SetEmbedded( const ScRange& rRange )
1492 bIsEmbedded = TRUE;
1493 aEmbedRange = rRange;
1496 void ScDocument::ResetEmbedded()
1498 bIsEmbedded = FALSE;
1499 aEmbedRange = ScRange();
1502 ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect )
1504 ScTable* pTable = pTab[nTab];
1505 if (!pTable)
1507 DBG_ERROR("GetRange ohne Tabelle");
1508 return ScRange();
1511 Rectangle aPosRect = rMMRect;
1512 if ( IsNegativePage( nTab ) )
1513 ScDrawLayer::MirrorRectRTL( aPosRect ); // always with positive (LTR) values
1515 long nSize;
1516 long nTwips;
1517 long nAdd;
1518 BOOL bEnd;
1520 nSize = 0;
1521 nTwips = (long) (aPosRect.Left() / HMM_PER_TWIPS);
1523 SCCOL nX1 = 0;
1524 bEnd = FALSE;
1525 while (!bEnd)
1527 nAdd = (long) pTable->GetColWidth(nX1);
1528 if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL)
1530 nSize += nAdd;
1531 ++nX1;
1533 else
1534 bEnd = TRUE;
1537 nTwips = (long) (aPosRect.Right() / HMM_PER_TWIPS);
1539 SCCOL nX2 = nX1;
1540 bEnd = FALSE;
1541 while (!bEnd)
1543 nAdd = (long) pTable->GetColWidth(nX2);
1544 if (nSize+nAdd < nTwips && nX2<MAXCOL)
1546 nSize += nAdd;
1547 ++nX2;
1549 else
1550 bEnd = TRUE;
1554 nSize = 0;
1555 nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS);
1557 SCROW nY1 = 0;
1558 ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter(
1559 *(pTable->GetRowFlagsArray()), nY1, MAXROW, CR_HIDDEN, 0,
1560 *(pTable->GetRowHeightArray()));
1561 bEnd = FALSE;
1562 while (!bEnd && aIter)
1564 nY1 = aIter.GetPos();
1565 nAdd = (long) *aIter;
1566 if (nSize+nAdd <= nTwips+1 && nY1<MAXROW)
1568 nSize += nAdd;
1569 ++nY1;
1570 ++aIter;
1572 else
1573 bEnd = TRUE;
1575 if (!aIter)
1576 nY1 = aIter.GetIterEnd(); // all hidden down to the bottom
1578 nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS);
1580 SCROW nY2 = nY1;
1581 aIter.NewLimits( nY2, MAXROW);
1582 bEnd = FALSE;
1583 while (!bEnd && aIter)
1585 nY2 = aIter.GetPos();
1586 nAdd = (long) *aIter;
1587 if (nSize+nAdd < nTwips && nY2<MAXROW)
1589 nSize += nAdd;
1590 ++nY2;
1591 ++aIter;
1593 else
1594 bEnd = TRUE;
1596 if (!aIter)
1597 nY2 = aIter.GetIterEnd(); // all hidden down to the bottom
1599 return ScRange( nX1,nY1,nTab, nX2,nY2,nTab );
1602 void ScDocument::SetEmbedded( const Rectangle& rRect ) // aus VisArea (1/100 mm)
1604 bIsEmbedded = TRUE;
1605 aEmbedRange = GetRange( nVisibleTab, rRect );
1608 // VisArea auf Zellgrenzen anpassen
1610 void lcl_SnapHor( ScTable* pTable, long& rVal, SCCOL& rStartCol )
1612 SCCOL nCol = 0;
1613 long nTwips = (long) (rVal / HMM_PER_TWIPS);
1614 long nSnap = 0;
1615 while ( nCol<MAXCOL )
1617 long nAdd = pTable->GetColWidth(nCol);
1618 if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol )
1620 nSnap += nAdd;
1621 ++nCol;
1623 else
1624 break;
1626 rVal = (long) ( nSnap * HMM_PER_TWIPS );
1627 rStartCol = nCol;
1630 void lcl_SnapVer( ScTable* pTable, long& rVal, SCROW& rStartRow )
1632 SCROW nRow = 0;
1633 long nTwips = (long) (rVal / HMM_PER_TWIPS);
1634 long nSnap = 0;
1635 ScCoupledCompressedArrayIterator< SCROW, BYTE, USHORT> aIter(
1636 *(pTable->GetRowFlagsArray()), nRow, MAXROW, CR_HIDDEN, 0,
1637 *(pTable->GetRowHeightArray()));
1638 while ( aIter )
1640 nRow = aIter.GetPos();
1641 long nAdd = *aIter;
1642 if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow )
1644 nSnap += nAdd;
1645 ++nRow;
1646 ++aIter;
1648 else
1649 break;
1651 if (!aIter)
1652 nRow = MAXROW; // all hidden down to the bottom
1653 rVal = (long) ( nSnap * HMM_PER_TWIPS );
1654 rStartRow = nRow;
1657 void ScDocument::SnapVisArea( Rectangle& rRect ) const
1659 ScTable* pTable = pTab[nVisibleTab];
1660 if (!pTable)
1662 DBG_ERROR("SetEmbedded ohne Tabelle");
1663 return;
1666 BOOL bNegativePage = IsNegativePage( nVisibleTab );
1667 if ( bNegativePage )
1668 ScDrawLayer::MirrorRectRTL( rRect ); // calculate with positive (LTR) values
1670 SCCOL nCol = 0;
1671 lcl_SnapHor( pTable, rRect.Left(), nCol );
1672 ++nCol; // mindestens eine Spalte
1673 lcl_SnapHor( pTable, rRect.Right(), nCol );
1675 SCROW nRow = 0;
1676 lcl_SnapVer( pTable, rRect.Top(), nRow );
1677 ++nRow; // mindestens eine Zeile
1678 lcl_SnapVer( pTable, rRect.Bottom(), nRow );
1680 if ( bNegativePage )
1681 ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle
1684 ScDocProtection* ScDocument::GetDocProtection() const
1686 return pDocProtection.get();
1689 void ScDocument::SetDocProtection(const ScDocProtection* pProtect)
1691 if (pProtect)
1692 pDocProtection.reset(new ScDocProtection(*pProtect));
1693 else
1694 pDocProtection.reset(NULL);
1697 BOOL ScDocument::IsDocProtected() const
1699 return pDocProtection.get() && pDocProtection->isProtected();
1702 BOOL ScDocument::IsDocEditable() const
1704 // import into read-only document is possible
1705 return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
1708 BOOL ScDocument::IsTabProtected( SCTAB nTab ) const
1710 if (VALIDTAB(nTab) && pTab[nTab])
1711 return pTab[nTab]->IsProtected();
1713 DBG_ERROR("Falsche Tabellennummer");
1714 return FALSE;
1717 ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const
1719 if (VALIDTAB(nTab) && pTab[nTab])
1720 return pTab[nTab]->GetProtection();
1722 return NULL;
1725 void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect)
1727 if (!ValidTab(nTab))
1728 return;
1730 pTab[nTab]->SetProtection(pProtect);
1733 void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest)
1735 if (!ValidTab(nTabSrc) || !ValidTab(nTabDest))
1736 return;
1738 pTab[nTabDest]->SetProtection( pTab[nTabSrc]->GetProtection() );
1741 const ScDocOptions& ScDocument::GetDocOptions() const
1743 DBG_ASSERT( pDocOptions, "No DocOptions! :-(" );
1744 return *pDocOptions;
1747 void ScDocument::SetDocOptions( const ScDocOptions& rOpt )
1749 USHORT d,m,y;
1751 DBG_ASSERT( pDocOptions, "No DocOptions! :-(" );
1752 *pDocOptions = rOpt;
1753 rOpt.GetDate( d,m,y );
1755 SvNumberFormatter* pFormatter = xPoolHelper->GetFormTable();
1756 pFormatter->ChangeNullDate( d,m,y );
1757 pFormatter->ChangeStandardPrec( (USHORT)rOpt.GetStdPrecision() );
1758 pFormatter->SetYear2000( rOpt.GetYear2000() );
1759 SetGrammar( rOpt.GetFormulaSyntax() );
1761 // Update the separators.
1762 ScCompiler::UpdateSeparatorsNative(
1763 rOpt.GetFormulaSepArg(), rOpt.GetFormulaSepArrayCol(), rOpt.GetFormulaSepArrayRow());
1766 const ScViewOptions& ScDocument::GetViewOptions() const
1768 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
1769 return *pViewOptions;
1772 void ScDocument::SetViewOptions( const ScViewOptions& rOpt )
1774 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
1775 *pViewOptions = rOpt;
1778 void ScDocument::GetLanguage( LanguageType& rLatin, LanguageType& rCjk, LanguageType& rCtl ) const
1780 rLatin = eLanguage;
1781 rCjk = eCjkLanguage;
1782 rCtl = eCtlLanguage;
1785 void ScDocument::SetLanguage( LanguageType eLatin, LanguageType eCjk, LanguageType eCtl )
1787 eLanguage = eLatin;
1788 eCjkLanguage = eCjk;
1789 eCtlLanguage = eCtl;
1790 if ( xPoolHelper.isValid() )
1792 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
1793 pPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) );
1794 pPool->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage, ATTR_CJK_FONT_LANGUAGE ) );
1795 pPool->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage, ATTR_CTL_FONT_LANGUAGE ) );
1798 UpdateDrawLanguages(); // set edit engine defaults in drawing layer pool
1801 void ScDocument::SetDrawDefaults()
1803 bSetDrawDefaults = TRUE;
1804 UpdateDrawDefaults();
1807 Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow,
1808 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
1810 if (!ValidTab(nTab) || !pTab[nTab])
1812 DBG_ERROR("GetMMRect: falsche Tabelle");
1813 return Rectangle(0,0,0,0);
1816 SCCOL i;
1817 Rectangle aRect;
1819 for (i=0; i<nStartCol; i++)
1820 aRect.Left() += GetColWidth(i,nTab);
1821 aRect.Top() += FastGetRowHeight( 0, nStartRow-1, nTab);
1823 aRect.Right() = aRect.Left();
1824 aRect.Bottom() = aRect.Top();
1826 for (i=nStartCol; i<=nEndCol; i++)
1827 aRect.Right() += GetColWidth(i,nTab);
1828 aRect.Bottom() += FastGetRowHeight( nStartRow, nEndRow, nTab);
1830 aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS);
1831 aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS);
1832 aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS);
1833 aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS);
1835 if ( IsNegativePage( nTab ) )
1836 ScDrawLayer::MirrorRectRTL( aRect );
1838 return aRect;
1841 void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions )
1843 delete pExtDocOptions;
1844 pExtDocOptions = pNewOptions;
1847 void ScDocument::DoMergeContents( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1848 SCCOL nEndCol, SCROW nEndRow )
1850 String aEmpty;
1851 String aTotal;
1852 String aCellStr;
1853 SCCOL nCol;
1854 SCROW nRow;
1855 for (nRow=nStartRow; nRow<=nEndRow; nRow++)
1856 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
1858 GetString(nCol,nRow,nTab,aCellStr);
1859 if (aCellStr.Len())
1861 if (aTotal.Len())
1862 aTotal += ' ';
1863 aTotal += aCellStr;
1865 if (nCol != nStartCol || nRow != nStartRow)
1866 SetString(nCol,nRow,nTab,aEmpty);
1869 SetString(nStartCol,nStartRow,nTab,aTotal);
1872 void ScDocument::DoMerge( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1873 SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions )
1875 ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 );
1876 ApplyAttr( nStartCol, nStartRow, nTab, aAttr );
1878 if ( nEndCol > nStartCol )
1879 ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR );
1880 if ( nEndRow > nStartRow )
1881 ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER );
1882 if ( nEndCol > nStartCol && nEndRow > nStartRow )
1883 ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1885 // remove all covered notes (removed captions are collected by drawing undo if active)
1886 USHORT nDelFlag = IDF_NOTE | (bDeleteCaptions ? 0 : IDF_NOCAPTIONS);
1887 if( nStartCol < nEndCol )
1888 DeleteAreaTab( nStartCol + 1, nStartRow, nEndCol, nStartRow, nTab, nDelFlag );
1889 if( nStartRow < nEndRow )
1890 DeleteAreaTab( nStartCol, nStartRow + 1, nEndCol, nEndRow, nTab, nDelFlag );
1893 void ScDocument::RemoveMerge( SCCOL nCol, SCROW nRow, SCTAB nTab )
1895 const ScMergeAttr* pAttr = (const ScMergeAttr*)
1896 GetAttr( nCol, nRow, nTab, ATTR_MERGE );
1898 if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 )
1899 return;
1901 SCCOL nEndCol = nCol + pAttr->GetColMerge() - 1;
1902 SCROW nEndRow = nRow + pAttr->GetRowMerge() - 1;
1904 RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1906 const ScMergeAttr* pDefAttr = (const ScMergeAttr*)
1907 &xPoolHelper->GetDocPool()->GetDefaultItem( ATTR_MERGE );
1908 ApplyAttr( nCol, nRow, nTab, *pDefAttr );
1911 void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab,
1912 SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow )
1914 if ( ValidTab(nTab) && pTab[nTab] )
1915 pTab[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow );
1918 void ScDocument::IncSizeRecalcLevel( SCTAB nTab )
1920 if ( ValidTab(nTab) && pTab[nTab] )
1921 pTab[nTab]->IncRecalcLevel();
1924 void ScDocument::DecSizeRecalcLevel( SCTAB nTab )
1926 if ( ValidTab(nTab) && pTab[nTab] )
1927 pTab[nTab]->DecRecalcLevel();