update dev300-m58
[ooovba.git] / sc / source / core / data / documen3.cxx
blob4c8cb802693291fae60f8bbf06de218b67ba23f7
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 "formulaparserpool.hxx"
84 #include "clipparam.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 GetLinkManager()->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 // Outline anpassen
1128 BOOL ScDocument::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, BOOL bShow )
1130 if ( ValidTab(nTab) && pTab[nTab] )
1131 return pTab[nTab]->UpdateOutlineCol( nStartCol, nEndCol, bShow );
1133 DBG_ERROR("missing tab");
1134 return FALSE;
1137 BOOL ScDocument::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, BOOL bShow )
1139 if ( ValidTab(nTab) && pTab[nTab] )
1140 return pTab[nTab]->UpdateOutlineRow( nStartRow, nEndRow, bShow );
1142 DBG_ERROR("missing tab");
1143 return FALSE;
1146 void ScDocument::Sort(SCTAB nTab, const ScSortParam& rSortParam, BOOL bKeepQuery)
1148 if ( ValidTab(nTab) && pTab[nTab] )
1150 BOOL bOldDisableIdle = IsIdleDisabled();
1151 DisableIdle( TRUE );
1152 pTab[nTab]->Sort(rSortParam, bKeepQuery);
1153 DisableIdle( bOldDisableIdle );
1157 SCSIZE ScDocument::Query(SCTAB nTab, const ScQueryParam& rQueryParam, BOOL bKeepSub)
1159 if ( ValidTab(nTab) && pTab[nTab] )
1160 return pTab[nTab]->Query((ScQueryParam&)rQueryParam, bKeepSub);
1162 DBG_ERROR("missing tab");
1163 return 0;
1167 BOOL ScDocument::ValidQuery( SCROW nRow, SCTAB nTab, const ScQueryParam& rQueryParam, BOOL* pSpecial )
1169 if ( ValidTab(nTab) && pTab[nTab] )
1170 return pTab[nTab]->ValidQuery( nRow, rQueryParam, pSpecial );
1172 DBG_ERROR("missing tab");
1173 return FALSE;
1177 void ScDocument::GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, String& rStr)
1179 if ( ValidTab(nTab) && pTab[nTab] )
1180 pTab[nTab]->GetUpperCellString( nCol, nRow, rStr );
1181 else
1182 rStr.Erase();
1185 BOOL ScDocument::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, ScQueryParam& rQueryParam)
1187 if ( ValidTab(nTab) && pTab[nTab] )
1188 return pTab[nTab]->CreateQueryParam(nCol1, nRow1, nCol2, nRow2, rQueryParam);
1190 DBG_ERROR("missing tab");
1191 return FALSE;
1194 BOOL ScDocument::HasAutoFilter( SCCOL nCurCol, SCROW nCurRow, SCTAB nCurTab )
1196 ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab );
1197 BOOL bHasAutoFilter = ( pDBData != NULL );
1199 if ( pDBData )
1201 if ( pDBData->HasHeader() )
1203 SCCOL nCol;
1204 SCROW nRow;
1205 INT16 nFlag;
1207 ScQueryParam aParam;
1208 pDBData->GetQueryParam( aParam );
1209 nRow = aParam.nRow1;
1211 for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ )
1213 nFlag = ((ScMergeFlagAttr*)
1214 GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))->
1215 GetValue();
1217 if ( (nFlag & SC_MF_AUTO) == 0 )
1218 bHasAutoFilter = FALSE;
1221 else
1222 bHasAutoFilter = FALSE;
1225 return bHasAutoFilter;
1228 BOOL ScDocument::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1229 SCTAB nTab )
1231 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1232 //if (VALIDTAB(nTab))
1233 // if (pTab[nTab])
1234 // return pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1236 //return FALSE;
1239 BOOL ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1240 SCTAB nTab )
1242 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1243 //if (VALIDTAB(nTab))
1244 // if (pTab[nTab])
1245 // return pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1247 //return FALSE;
1250 void ScDocument::UpdateDynamicEndRow(ScDBData& rDBData) const
1252 SCCOL nCol1, nCol2;
1253 SCROW nRow1, nRow2;
1254 SCTAB nTab;
1255 rDBData.GetArea(nTab, nCol1, nRow1, nCol2, nRow2);
1256 SCCOL nCol1a = nCol1, nCol2a = nCol2;
1257 SCROW nRow1a = nRow1, nRow2a = nRow2;
1258 GetDataArea(nTab, nCol1a, nRow1a, nCol2a, nRow2a, false);
1259 rDBData.SetDynamicEndRow(nRow2a);
1263 // GetFilterEntries - Eintraege fuer AutoFilter-Listbox
1266 BOOL ScDocument::GetFilterEntries(
1267 SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates)
1269 if ( ValidTab(nTab) && pTab[nTab] && pDBCollection )
1271 ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, FALSE); //!??
1272 if (pDBData)
1274 UpdateDynamicEndRow(*pDBData);
1275 SCTAB nAreaTab;
1276 SCCOL nStartCol;
1277 SCROW nStartRow;
1278 SCCOL nEndCol;
1279 SCROW nEndRow;
1280 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1281 if (pDBData->HasHeader())
1282 ++nStartRow;
1284 ScQueryParam aParam;
1285 pDBData->GetQueryParam( aParam );
1286 nEndRow = aParam.nDynamicEndRow;
1287 rStrings.SetCaseSensitive( aParam.bCaseSens );
1289 // return all filter entries, if a filter condition is connected with a boolean OR
1290 if ( bFilter )
1292 SCSIZE nEntryCount = aParam.GetEntryCount();
1293 for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i )
1295 ScQueryEntry& rEntry = aParam.GetEntry(i);
1296 if ( rEntry.eConnect != SC_AND )
1298 bFilter = false;
1299 break;
1304 if ( bFilter )
1306 pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates );
1308 else
1310 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
1313 return TRUE;
1317 return FALSE;
1321 // GetFilterEntriesArea - Eintraege fuer Filter-Dialog
1324 BOOL ScDocument::GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow,
1325 SCTAB nTab, TypedScStrCollection& rStrings, bool& rHasDates )
1327 if ( ValidTab(nTab) && pTab[nTab] )
1329 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
1330 return TRUE;
1333 return FALSE;
1337 // GetDataEntries - Eintraege fuer Auswahlliste-Listbox (keine Zahlen / Formeln)
1340 BOOL ScDocument::GetDataEntries( SCCOL nCol, SCROW nRow, SCTAB nTab,
1341 TypedScStrCollection& rStrings, BOOL bLimit )
1343 if( !bLimit )
1345 /* Try to generate the list from list validation. This part is skipped,
1346 if bLimit==TRUE, because in that case this function is called to get
1347 cell values for auto completion on input. */
1348 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
1349 if( nValidation )
1351 const ScValidationData* pData = GetValidationEntry( nValidation );
1352 if( pData && pData->FillSelectionList( rStrings, ScAddress( nCol, nRow, nTab ) ) )
1353 return TRUE;
1357 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
1358 //if (ValidTab(nTab) && pTab[nTab])
1359 // return pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
1361 //return FALSE;
1365 // GetFormulaEntries - Eintraege fuer Formel-AutoEingabe
1368 // Funktionen werden als 1 schon vom InputHandler eingefuegt
1369 #define SC_STRTYPE_NAMES 2
1370 #define SC_STRTYPE_DBNAMES 3
1371 #define SC_STRTYPE_HEADERS 4
1373 BOOL ScDocument::GetFormulaEntries( TypedScStrCollection& rStrings )
1375 USHORT i;
1378 // Bereichsnamen
1381 if ( pRangeName )
1383 USHORT nRangeCount = pRangeName->GetCount();
1384 for ( i=0; i<nRangeCount; i++ )
1386 ScRangeData* pData = (*pRangeName)[i];
1387 if (pData)
1389 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_NAMES );
1390 if ( !rStrings.Insert(pNew) )
1391 delete pNew;
1397 // Datenbank-Bereiche
1400 if ( pDBCollection )
1402 USHORT nDBCount = pDBCollection->GetCount();
1403 for ( i=0; i<nDBCount; i++ )
1405 ScDBData* pData = (*pDBCollection)[i];
1406 if (pData)
1408 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_DBNAMES );
1409 if ( !rStrings.Insert(pNew) )
1410 delete pNew;
1416 // Inhalte von Beschriftungsbereichen
1419 ScRangePairList* pLists[2];
1420 pLists[0] = GetColNameRanges();
1421 pLists[1] = GetRowNameRanges();
1422 for (USHORT nListNo=0; nListNo<2; nListNo++)
1424 ScRangePairList* pList = pLists[nListNo];
1425 if (pList)
1426 for ( ScRangePair* pPair = pList->First(); pPair; pPair = pList->Next() )
1428 ScRange aRange = pPair->GetRange(0);
1429 ScCellIterator aIter( this, aRange );
1430 for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() )
1431 if ( pCell->HasStringData() )
1433 String aStr = pCell->GetStringData();
1434 TypedStrData* pNew = new TypedStrData( aStr, 0.0, SC_STRTYPE_HEADERS );
1435 if ( !rStrings.Insert(pNew) )
1436 delete pNew;
1441 return TRUE;
1445 BOOL ScDocument::IsEmbedded() const
1447 return bIsEmbedded;
1450 void ScDocument::GetEmbedded( ScRange& rRange ) const
1452 rRange = aEmbedRange;
1455 Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm
1457 Rectangle aRect;
1458 ScTable* pTable = pTab[aEmbedRange.aStart.Tab()];
1459 if (!pTable)
1461 DBG_ERROR("GetEmbeddedRect ohne Tabelle");
1463 else
1465 SCCOL i;
1467 for (i=0; i<aEmbedRange.aStart.Col(); i++)
1468 aRect.Left() += pTable->GetColWidth(i);
1469 aRect.Top() += pTable->GetRowHeight( 0, aEmbedRange.aStart.Row() - 1);
1470 aRect.Right() = aRect.Left();
1471 for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++)
1472 aRect.Right() += pTable->GetColWidth(i);
1473 aRect.Bottom() = aRect.Top();
1474 aRect.Bottom() += pTable->GetRowHeight( aEmbedRange.aStart.Row(), aEmbedRange.aEnd.Row());
1476 aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS );
1477 aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS );
1478 aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS );
1479 aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS );
1481 return aRect;
1484 void ScDocument::SetEmbedded( const ScRange& rRange )
1486 bIsEmbedded = TRUE;
1487 aEmbedRange = rRange;
1490 void ScDocument::ResetEmbedded()
1492 bIsEmbedded = FALSE;
1493 aEmbedRange = ScRange();
1496 ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect )
1498 ScTable* pTable = pTab[nTab];
1499 if (!pTable)
1501 DBG_ERROR("GetRange ohne Tabelle");
1502 return ScRange();
1505 Rectangle aPosRect = rMMRect;
1506 if ( IsNegativePage( nTab ) )
1507 ScDrawLayer::MirrorRectRTL( aPosRect ); // always with positive (LTR) values
1509 long nSize;
1510 long nTwips;
1511 long nAdd;
1512 BOOL bEnd;
1514 nSize = 0;
1515 nTwips = (long) (aPosRect.Left() / HMM_PER_TWIPS);
1517 SCCOL nX1 = 0;
1518 bEnd = FALSE;
1519 while (!bEnd)
1521 nAdd = (long) pTable->GetColWidth(nX1);
1522 if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL)
1524 nSize += nAdd;
1525 ++nX1;
1527 else
1528 bEnd = TRUE;
1531 nTwips = (long) (aPosRect.Right() / HMM_PER_TWIPS);
1533 SCCOL nX2 = nX1;
1534 bEnd = FALSE;
1535 while (!bEnd)
1537 nAdd = (long) pTable->GetColWidth(nX2);
1538 if (nSize+nAdd < nTwips && nX2<MAXCOL)
1540 nSize += nAdd;
1541 ++nX2;
1543 else
1544 bEnd = TRUE;
1548 nSize = 0;
1549 nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS);
1551 SCROW nY1 = 0;
1552 bEnd = FALSE;
1553 for (SCROW i = nY1; i <= MAXROW && !bEnd; ++i)
1555 if (pTable->RowHidden(i))
1556 continue;
1558 nY1 = i;
1559 nAdd = static_cast<long>(pTable->GetRowHeight(i));
1560 if (nSize+nAdd <= nTwips+1 && nY1<MAXROW)
1562 nSize += nAdd;
1563 ++nY1;
1565 else
1566 bEnd = TRUE;
1568 if (!bEnd)
1569 nY1 = MAXROW; // all hidden down to the bottom
1571 nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS);
1573 SCROW nY2 = nY1;
1574 bEnd = FALSE;
1575 for (SCROW i = nY2; i <= MAXROW && !bEnd; ++i)
1577 nY2 = i;
1578 nAdd = static_cast<long>(pTable->GetRowHeight(i));
1579 if (nSize+nAdd < nTwips && nY2<MAXROW)
1581 nSize += nAdd;
1582 ++nY2;
1584 else
1585 bEnd = TRUE;
1587 if (!bEnd)
1588 nY2 = MAXROW; // all hidden down to the bottom
1590 return ScRange( nX1,nY1,nTab, nX2,nY2,nTab );
1593 void ScDocument::SetEmbedded( const Rectangle& rRect ) // aus VisArea (1/100 mm)
1595 bIsEmbedded = TRUE;
1596 aEmbedRange = GetRange( nVisibleTab, rRect );
1599 // VisArea auf Zellgrenzen anpassen
1601 void lcl_SnapHor( ScTable* pTable, long& rVal, SCCOL& rStartCol )
1603 SCCOL nCol = 0;
1604 long nTwips = (long) (rVal / HMM_PER_TWIPS);
1605 long nSnap = 0;
1606 while ( nCol<MAXCOL )
1608 long nAdd = pTable->GetColWidth(nCol);
1609 if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol )
1611 nSnap += nAdd;
1612 ++nCol;
1614 else
1615 break;
1617 rVal = (long) ( nSnap * HMM_PER_TWIPS );
1618 rStartCol = nCol;
1621 void lcl_SnapVer( ScTable* pTable, long& rVal, SCROW& rStartRow )
1623 SCROW nRow = 0;
1624 long nTwips = (long) (rVal / HMM_PER_TWIPS);
1625 long nSnap = 0;
1627 bool bFound = false;
1628 for (SCROW i = nRow; i <= MAXROW; ++i)
1630 SCROW nLastRow;
1631 if (pTable->RowHidden(i, NULL, &nLastRow))
1633 i = nLastRow;
1634 continue;
1637 nRow = i;
1638 long nAdd = pTable->GetRowHeight(i);
1639 if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow )
1641 nSnap += nAdd;
1642 ++nRow;
1644 else
1646 bFound = true;
1647 break;
1650 if (!bFound)
1651 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 xPoolHelper->SetFormTableOpt(rOpt);
1757 SetGrammar( rOpt.GetFormulaSyntax() );
1759 // Update the separators.
1760 ScCompiler::UpdateSeparatorsNative(
1761 rOpt.GetFormulaSepArg(), rOpt.GetFormulaSepArrayCol(), rOpt.GetFormulaSepArrayRow());
1764 const ScViewOptions& ScDocument::GetViewOptions() const
1766 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
1767 return *pViewOptions;
1770 void ScDocument::SetViewOptions( const ScViewOptions& rOpt )
1772 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
1773 *pViewOptions = rOpt;
1776 void ScDocument::GetLanguage( LanguageType& rLatin, LanguageType& rCjk, LanguageType& rCtl ) const
1778 rLatin = eLanguage;
1779 rCjk = eCjkLanguage;
1780 rCtl = eCtlLanguage;
1783 void ScDocument::SetLanguage( LanguageType eLatin, LanguageType eCjk, LanguageType eCtl )
1785 eLanguage = eLatin;
1786 eCjkLanguage = eCjk;
1787 eCtlLanguage = eCtl;
1788 if ( xPoolHelper.isValid() )
1790 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
1791 pPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) );
1792 pPool->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage, ATTR_CJK_FONT_LANGUAGE ) );
1793 pPool->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage, ATTR_CTL_FONT_LANGUAGE ) );
1796 UpdateDrawLanguages(); // set edit engine defaults in drawing layer pool
1799 void ScDocument::SetDrawDefaults()
1801 bSetDrawDefaults = TRUE;
1802 UpdateDrawDefaults();
1805 Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow,
1806 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
1808 if (!ValidTab(nTab) || !pTab[nTab])
1810 DBG_ERROR("GetMMRect: falsche Tabelle");
1811 return Rectangle(0,0,0,0);
1814 SCCOL i;
1815 Rectangle aRect;
1817 for (i=0; i<nStartCol; i++)
1818 aRect.Left() += GetColWidth(i,nTab);
1819 aRect.Top() += FastGetRowHeight( 0, nStartRow-1, nTab);
1821 aRect.Right() = aRect.Left();
1822 aRect.Bottom() = aRect.Top();
1824 for (i=nStartCol; i<=nEndCol; i++)
1825 aRect.Right() += GetColWidth(i,nTab);
1826 aRect.Bottom() += FastGetRowHeight( nStartRow, nEndRow, nTab);
1828 aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS);
1829 aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS);
1830 aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS);
1831 aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS);
1833 if ( IsNegativePage( nTab ) )
1834 ScDrawLayer::MirrorRectRTL( aRect );
1836 return aRect;
1839 void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions )
1841 delete pExtDocOptions;
1842 pExtDocOptions = pNewOptions;
1845 void ScDocument::DoMergeContents( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1846 SCCOL nEndCol, SCROW nEndRow )
1848 String aEmpty;
1849 String aTotal;
1850 String aCellStr;
1851 SCCOL nCol;
1852 SCROW nRow;
1853 for (nRow=nStartRow; nRow<=nEndRow; nRow++)
1854 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
1856 GetString(nCol,nRow,nTab,aCellStr);
1857 if (aCellStr.Len())
1859 if (aTotal.Len())
1860 aTotal += ' ';
1861 aTotal += aCellStr;
1863 if (nCol != nStartCol || nRow != nStartRow)
1864 SetString(nCol,nRow,nTab,aEmpty);
1867 SetString(nStartCol,nStartRow,nTab,aTotal);
1870 void ScDocument::DoMerge( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1871 SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions )
1873 ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 );
1874 ApplyAttr( nStartCol, nStartRow, nTab, aAttr );
1876 if ( nEndCol > nStartCol )
1877 ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR );
1878 if ( nEndRow > nStartRow )
1879 ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER );
1880 if ( nEndCol > nStartCol && nEndRow > nStartRow )
1881 ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1883 // remove all covered notes (removed captions are collected by drawing undo if active)
1884 USHORT nDelFlag = IDF_NOTE | (bDeleteCaptions ? 0 : IDF_NOCAPTIONS);
1885 if( nStartCol < nEndCol )
1886 DeleteAreaTab( nStartCol + 1, nStartRow, nEndCol, nStartRow, nTab, nDelFlag );
1887 if( nStartRow < nEndRow )
1888 DeleteAreaTab( nStartCol, nStartRow + 1, nEndCol, nEndRow, nTab, nDelFlag );
1891 void ScDocument::RemoveMerge( SCCOL nCol, SCROW nRow, SCTAB nTab )
1893 const ScMergeAttr* pAttr = (const ScMergeAttr*)
1894 GetAttr( nCol, nRow, nTab, ATTR_MERGE );
1896 if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 )
1897 return;
1899 SCCOL nEndCol = nCol + pAttr->GetColMerge() - 1;
1900 SCROW nEndRow = nRow + pAttr->GetRowMerge() - 1;
1902 RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1904 const ScMergeAttr* pDefAttr = (const ScMergeAttr*)
1905 &xPoolHelper->GetDocPool()->GetDefaultItem( ATTR_MERGE );
1906 ApplyAttr( nCol, nRow, nTab, *pDefAttr );
1909 void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab,
1910 SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow )
1912 if ( ValidTab(nTab) && pTab[nTab] )
1913 pTab[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow );
1916 void ScDocument::IncSizeRecalcLevel( SCTAB nTab )
1918 if ( ValidTab(nTab) && pTab[nTab] )
1919 pTab[nTab]->IncRecalcLevel();
1922 void ScDocument::DecSizeRecalcLevel( SCTAB nTab )
1924 if ( ValidTab(nTab) && pTab[nTab] )
1925 pTab[nTab]->DecRecalcLevel();