merge the formfield patch from ooo-build
[ooovba.git] / sc / source / core / data / documen3.cxx
blobd8e4101a20bb4f5bc966a8f3bb4bdbed9b258eea
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() const
446 ScDocument* pThis = const_cast<ScDocument*>(this);
447 if (!pExternalRefMgr.get())
448 pThis->pExternalRefMgr.reset( new ScExternalRefManager( pThis));
450 return pExternalRefMgr.get();
453 bool ScDocument::IsInExternalReferenceMarking() const
455 return pExternalRefMgr.get() && pExternalRefMgr->isInReferenceMarking();
458 void ScDocument::MarkUsedExternalReferences()
460 if (!pExternalRefMgr.get())
461 return;
462 if (!pExternalRefMgr->hasExternalData())
463 return;
464 // Charts.
465 bool bAllMarked = pExternalRefMgr->markUsedByLinkListeners();
466 // Formula cells.
467 for (SCTAB nTab = 0; !bAllMarked && nTab < nMaxTableNumber; ++nTab)
469 if (pTab[nTab])
470 bAllMarked = pTab[nTab]->MarkUsedExternalReferences();
472 /* NOTE: Conditional formats and validation objects are marked when
473 * collecting them during export. */
476 ScFormulaParserPool& ScDocument::GetFormulaParserPool() const
478 if( !mxFormulaParserPool.get() )
479 mxFormulaParserPool.reset( new ScFormulaParserPool( *this ) );
480 return *mxFormulaParserPool;
483 ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, BOOL bCreate )
485 ScOutlineTable* pVal = NULL;
487 if (VALIDTAB(nTab))
488 if (pTab[nTab])
490 pVal = pTab[nTab]->GetOutlineTable();
491 if (!pVal)
492 if (bCreate)
494 pTab[nTab]->StartOutlineTable();
495 pVal = pTab[nTab]->GetOutlineTable();
499 return pVal;
502 BOOL ScDocument::SetOutlineTable( SCTAB nTab, const ScOutlineTable* pNewOutline )
504 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->SetOutlineTable(pNewOutline);
505 //if (VALIDTAB(nTab))
506 // if (pTab[nTab])
507 // return pTab[nTab]->SetOutlineTable(pNewOutline);
509 //return FALSE;
512 void ScDocument::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow,
513 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
515 if (VALIDTAB(nTab) && pTab[nTab])
516 pTab[nTab]->DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
519 BOOL ScDocument::TestRemoveSubTotals( SCTAB nTab, const ScSubTotalParam& rParam )
521 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->TestRemoveSubTotals( rParam );
522 //if (VALIDTAB(nTab) && pTab[nTab] )
523 // return pTab[nTab]->TestRemoveSubTotals( rParam );
525 //return FALSE;
528 void ScDocument::RemoveSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
530 if ( VALIDTAB(nTab) && pTab[nTab] )
531 pTab[nTab]->RemoveSubTotals( rParam );
534 BOOL ScDocument::DoSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
536 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->DoSubTotals( rParam );
537 //if (VALIDTAB(nTab))
538 // if (pTab[nTab])
539 // return pTab[nTab]->DoSubTotals( rParam );
541 //return FALSE;
544 BOOL ScDocument::HasSubTotalCells( const ScRange& rRange )
546 ScCellIterator aIter( this, rRange );
547 ScBaseCell* pCell = aIter.GetFirst();
548 while (pCell)
550 if ( pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->IsSubTotal() )
551 return TRUE;
553 pCell = aIter.GetNext();
555 return FALSE; // none found
558 // kopiert aus diesem Dokument die Zellen von Positionen, an denen in pPosDoc
559 // auch Zellen stehen, nach pDestDoc
561 void ScDocument::CopyUpdated( ScDocument* pPosDoc, ScDocument* pDestDoc )
563 SCTAB nCount = GetTableCount();
564 for (SCTAB nTab=0; nTab<nCount; nTab++)
565 if (pTab[nTab] && pPosDoc->pTab[nTab] && pDestDoc->pTab[nTab])
566 pTab[nTab]->CopyUpdated( pPosDoc->pTab[nTab], pDestDoc->pTab[nTab] );
569 void ScDocument::CopyScenario( SCTAB nSrcTab, SCTAB nDestTab, BOOL bNewScenario )
571 if (ValidTab(nSrcTab) && ValidTab(nDestTab) && pTab[nSrcTab] && pTab[nDestTab])
573 // Flags fuer aktive Szenarios richtig setzen
574 // und aktuelle Werte in bisher aktive Szenarios zurueckschreiben
576 ScRangeList aRanges = *pTab[nSrcTab]->GetScenarioRanges();
577 const ULONG nRangeCount = aRanges.Count();
579 // nDestTab ist die Zieltabelle
580 for ( SCTAB nTab = nDestTab+1;
581 nTab<=MAXTAB && pTab[nTab] && pTab[nTab]->IsScenario();
582 nTab++ )
584 if ( pTab[nTab]->IsActiveScenario() ) // auch wenn's dasselbe Szenario ist
586 BOOL bTouched = FALSE;
587 for ( ULONG nR=0; nR<nRangeCount && !bTouched; nR++)
589 const ScRange* pRange = aRanges.GetObject(nR);
590 if ( pTab[nTab]->HasScenarioRange( *pRange ) )
591 bTouched = TRUE;
593 if (bTouched)
595 pTab[nTab]->SetActiveScenario(FALSE);
596 if ( pTab[nTab]->GetScenarioFlags() & SC_SCENARIO_TWOWAY )
597 pTab[nTab]->CopyScenarioFrom( pTab[nDestTab] );
602 pTab[nSrcTab]->SetActiveScenario(TRUE); // da kommt's her...
603 if (!bNewScenario) // Daten aus dem ausgewaehlten Szenario kopieren
605 BOOL bOldAutoCalc = GetAutoCalc();
606 SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden
607 pTab[nSrcTab]->CopyScenarioTo( pTab[nDestTab] );
608 SetDirty();
609 SetAutoCalc( bOldAutoCalc );
614 void ScDocument::MarkScenario( SCTAB nSrcTab, SCTAB nDestTab, ScMarkData& rDestMark,
615 BOOL bResetMark, USHORT nNeededBits ) const
617 if (bResetMark)
618 rDestMark.ResetMark();
620 if (ValidTab(nSrcTab) && pTab[nSrcTab])
621 pTab[nSrcTab]->MarkScenarioIn( rDestMark, nNeededBits );
623 rDestMark.SetAreaTab( nDestTab );
626 BOOL ScDocument::HasScenarioRange( SCTAB nTab, const ScRange& rRange ) const
628 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->HasScenarioRange( rRange );
629 //if (ValidTab(nTab) && pTab[nTab])
630 // return pTab[nTab]->HasScenarioRange( rRange );
632 //return FALSE;
635 const ScRangeList* ScDocument::GetScenarioRanges( SCTAB nTab ) const
637 if (ValidTab(nTab) && pTab[nTab])
638 return pTab[nTab]->GetScenarioRanges();
640 return NULL;
643 BOOL ScDocument::IsActiveScenario( SCTAB nTab ) const
645 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->IsActiveScenario( );
646 //if (ValidTab(nTab) && pTab[nTab])
647 // return pTab[nTab]->IsActiveScenario();
649 //return FALSE;
652 void ScDocument::SetActiveScenario( SCTAB nTab, BOOL bActive )
654 if (ValidTab(nTab) && pTab[nTab])
655 pTab[nTab]->SetActiveScenario( bActive );
658 BOOL ScDocument::TestCopyScenario( SCTAB nSrcTab, SCTAB nDestTab ) const
660 if (ValidTab(nSrcTab) && ValidTab(nDestTab))
661 return pTab[nSrcTab]->TestCopyScenarioTo( pTab[nDestTab] );
663 DBG_ERROR("falsche Tabelle bei TestCopyScenario");
664 return FALSE;
667 void ScDocument::AddUnoObject( SfxListener& rObject )
669 if (!pUnoBroadcaster)
670 pUnoBroadcaster = new SfxBroadcaster;
672 rObject.StartListening( *pUnoBroadcaster );
675 void ScDocument::RemoveUnoObject( SfxListener& rObject )
677 if (pUnoBroadcaster)
679 rObject.EndListening( *pUnoBroadcaster );
681 if ( bInUnoBroadcast )
683 // #107294# Broadcasts from ScDocument::BroadcastUno are the only way that
684 // uno object methods are called without holding a reference.
686 // If RemoveUnoObject is called from an object dtor in the finalizer thread
687 // while the main thread is calling BroadcastUno, the dtor thread must wait
688 // (or the object's Notify might try to access a deleted object).
689 // The SolarMutex can't be locked here because if a component is called from
690 // a VCL event, the main thread has the SolarMutex locked all the time.
692 // This check is done after calling EndListening, so a later BroadcastUno call
693 // won't touch this object.
695 vos::IMutex& rSolarMutex = Application::GetSolarMutex();
696 if ( rSolarMutex.tryToAcquire() )
698 // BroadcastUno is always called with the SolarMutex locked, so if it
699 // can be acquired, this is within the same thread (should not happen)
700 DBG_ERRORFILE( "RemoveUnoObject called from BroadcastUno" );
701 rSolarMutex.release();
703 else
705 // let the thread that called BroadcastUno continue
706 while ( bInUnoBroadcast )
708 vos::OThread::yield();
713 else
715 DBG_ERROR("No Uno broadcaster");
719 void ScDocument::BroadcastUno( const SfxHint &rHint )
721 if (pUnoBroadcaster)
723 bInUnoBroadcast = TRUE;
724 pUnoBroadcaster->Broadcast( rHint );
725 bInUnoBroadcast = FALSE;
727 // During Broadcast notification, Uno objects can add to pUnoListenerCalls.
728 // The listener calls must be processed after completing the broadcast,
729 // because they can add or remove objects from pUnoBroadcaster.
731 if ( pUnoListenerCalls && rHint.ISA( SfxSimpleHint ) &&
732 ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DATACHANGED &&
733 !bInUnoListenerCall )
735 // Listener calls may lead to BroadcastUno calls again. The listener calls
736 // are not nested, instead the calls are collected in the list, and the
737 // outermost call executes them all.
739 ScChartLockGuard aChartLockGuard(this);
740 bInUnoListenerCall = TRUE;
741 pUnoListenerCalls->ExecuteAndClear();
742 bInUnoListenerCall = FALSE;
747 void ScDocument::AddUnoListenerCall( const uno::Reference<util::XModifyListener>& rListener,
748 const lang::EventObject& rEvent )
750 DBG_ASSERT( bInUnoBroadcast, "AddUnoListenerCall is supposed to be called from BroadcastUno only" );
752 if ( !pUnoListenerCalls )
753 pUnoListenerCalls = new ScUnoListenerCalls;
754 pUnoListenerCalls->Add( rListener, rEvent );
757 void ScDocument::BeginUnoRefUndo()
759 DBG_ASSERT( !pUnoRefUndoList, "BeginUnoRefUndo twice" );
760 delete pUnoRefUndoList;
762 pUnoRefUndoList = new ScUnoRefList;
765 ScUnoRefList* ScDocument::EndUnoRefUndo()
767 ScUnoRefList* pRet = pUnoRefUndoList;
768 pUnoRefUndoList = NULL;
769 return pRet; // must be deleted by caller!
772 void ScDocument::AddUnoRefChange( sal_Int64 nId, const ScRangeList& rOldRanges )
774 if ( pUnoRefUndoList )
775 pUnoRefUndoList->Add( nId, rOldRanges );
778 sal_Int64 ScDocument::GetNewUnoId()
780 return ++nUnoObjectId;
783 void ScDocument::UpdateReference( UpdateRefMode eUpdateRefMode,
784 SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
785 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
786 SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
787 ScDocument* pUndoDoc, BOOL bIncludeDraw )
789 PutInOrder( nCol1, nCol2 );
790 PutInOrder( nRow1, nRow2 );
791 PutInOrder( nTab1, nTab2 );
792 if (VALIDTAB(nTab1) && VALIDTAB(nTab2))
794 BOOL bExpandRefsOld = IsExpandRefs();
795 if ( eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0 || nDz > 0) )
796 SetExpandRefs( SC_MOD()->GetInputOptions().GetExpandRefs() );
797 SCTAB i;
798 SCTAB iMax;
799 if ( eUpdateRefMode == URM_COPY )
801 i = nTab1;
802 iMax = nTab2;
804 else
806 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
807 xColNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
808 xRowNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
809 pDBCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
810 pRangeName->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
811 if ( pDPCollection )
812 pDPCollection->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
813 UpdateChartRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
814 UpdateRefAreaLinks( eUpdateRefMode, aRange, nDx, nDy, nDz );
815 if ( pCondFormList )
816 pCondFormList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
817 if ( pValidationList )
818 pValidationList->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
819 if ( pDetOpList )
820 pDetOpList->UpdateReference( this, eUpdateRefMode, aRange, nDx, nDy, nDz );
821 if ( pUnoBroadcaster )
822 pUnoBroadcaster->Broadcast( ScUpdateRefHint(
823 eUpdateRefMode, aRange, nDx, nDy, nDz ) );
824 i = 0;
825 iMax = MAXTAB;
827 for ( ; i<=iMax; i++)
828 if (pTab[i])
829 pTab[i]->UpdateReference(
830 eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
831 nDx, nDy, nDz, pUndoDoc, bIncludeDraw );
833 if ( bIsEmbedded )
835 SCCOL theCol1;
836 SCROW theRow1;
837 SCTAB theTab1;
838 SCCOL theCol2;
839 SCROW theRow2;
840 SCTAB theTab2;
841 theCol1 = aEmbedRange.aStart.Col();
842 theRow1 = aEmbedRange.aStart.Row();
843 theTab1 = aEmbedRange.aStart.Tab();
844 theCol2 = aEmbedRange.aEnd.Col();
845 theRow2 = aEmbedRange.aEnd.Row();
846 theTab2 = aEmbedRange.aEnd.Tab();
847 if ( ScRefUpdate::Update( this, eUpdateRefMode, nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
848 nDx,nDy,nDz, theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
850 aEmbedRange = ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
853 SetExpandRefs( bExpandRefsOld );
855 // #30428# after moving, no clipboard move ref-updates are possible
856 if ( eUpdateRefMode != URM_COPY && IsClipboardSource() )
858 ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
859 if (pClipDoc)
860 pClipDoc->GetClipParam().mbCutMode = false;
865 void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDoc,
866 const ScMarkData& rMark, ScDocument* pUndoDoc )
868 DBG_ASSERT(pClipDoc->bIsClip, "UpdateTranspose: kein Clip");
870 ScRange aSource;
871 ScClipParam& rClipParam = GetClipParam();
872 if (rClipParam.maRanges.Count())
873 aSource = *rClipParam.maRanges.First();
874 ScAddress aDest = rDestPos;
876 SCTAB nClipTab = 0;
877 for (SCTAB nDestTab=0; nDestTab<=MAXTAB && pTab[nDestTab]; nDestTab++)
878 if (rMark.GetTableSelect(nDestTab))
880 while (!pClipDoc->pTab[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
881 aSource.aStart.SetTab( nClipTab );
882 aSource.aEnd.SetTab( nClipTab );
883 aDest.SetTab( nDestTab );
885 // wie UpdateReference
887 pRangeName->UpdateTranspose( aSource, aDest ); // vor den Zellen!
888 for (SCTAB i=0; i<=MAXTAB; i++)
889 if (pTab[i])
890 pTab[i]->UpdateTranspose( aSource, aDest, pUndoDoc );
892 nClipTab = (nClipTab+1) % (MAXTAB+1);
896 void ScDocument::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
898 //! pDBCollection
899 //! pPivotCollection
900 //! UpdateChartRef
902 pRangeName->UpdateGrow( rArea, nGrowX, nGrowY );
904 for (SCTAB i=0; i<=MAXTAB && pTab[i]; i++)
905 pTab[i]->UpdateGrow( rArea, nGrowX, nGrowY );
908 void ScDocument::Fill(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
909 ULONG nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
910 double nStepValue, double nMaxValue)
912 PutInOrder( nCol1, nCol2 );
913 PutInOrder( nRow1, nRow2 );
914 for (SCTAB i=0; i <= MAXTAB; i++)
915 if (pTab[i])
916 if (rMark.GetTableSelect(i))
917 pTab[i]->Fill(nCol1, nRow1, nCol2, nRow2,
918 nFillCount, eFillDir, eFillCmd, eFillDateCmd,
919 nStepValue, nMaxValue);
922 String ScDocument::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
924 SCTAB nTab = rSource.aStart.Tab();
925 if (pTab[nTab])
926 return pTab[nTab]->GetAutoFillPreview( rSource, nEndX, nEndY );
928 return EMPTY_STRING;
931 void ScDocument::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
932 USHORT nFormatNo, const ScMarkData& rMark )
934 PutInOrder( nStartCol, nEndCol );
935 PutInOrder( nStartRow, nEndRow );
936 for (SCTAB i=0; i <= MAXTAB; i++)
937 if (pTab[i])
938 if (rMark.GetTableSelect(i))
939 pTab[i]->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo );
942 void ScDocument::GetAutoFormatData(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
943 ScAutoFormatData& rData)
945 if (VALIDTAB(nTab))
947 if (pTab[nTab])
949 PutInOrder(nStartCol, nEndCol);
950 PutInOrder(nStartRow, nEndRow);
951 pTab[nTab]->GetAutoFormatData(nStartCol, nStartRow, nEndCol, nEndRow, rData);
956 // static
957 void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem& rSearchItem,
958 SCCOL& rCol, SCROW& rRow )
960 USHORT nCommand = rSearchItem.GetCommand();
961 BOOL bReplace = ( nCommand == SVX_SEARCHCMD_REPLACE ||
962 nCommand == SVX_SEARCHCMD_REPLACE_ALL );
963 if ( rSearchItem.GetBackward() )
965 if ( rSearchItem.GetRowDirection() )
967 if ( rSearchItem.GetPattern() )
969 rCol = MAXCOL;
970 rRow = MAXROW+1;
972 else if ( bReplace )
974 rCol = MAXCOL;
975 rRow = MAXROW;
977 else
979 rCol = MAXCOL+1;
980 rRow = MAXROW;
983 else
985 if ( rSearchItem.GetPattern() )
987 rCol = MAXCOL+1;
988 rRow = MAXROW;
990 else if ( bReplace )
992 rCol = MAXCOL;
993 rRow = MAXROW;
995 else
997 rCol = MAXCOL;
998 rRow = MAXROW+1;
1002 else
1004 if ( rSearchItem.GetRowDirection() )
1006 if ( rSearchItem.GetPattern() )
1008 rCol = 0;
1009 rRow = (SCROW) -1;
1011 else if ( bReplace )
1013 rCol = 0;
1014 rRow = 0;
1016 else
1018 rCol = (SCCOL) -1;
1019 rRow = 0;
1022 else
1024 if ( rSearchItem.GetPattern() )
1026 rCol = (SCCOL) -1;
1027 rRow = 0;
1029 else if ( bReplace )
1031 rCol = 0;
1032 rRow = 0;
1034 else
1036 rCol = 0;
1037 rRow = (SCROW) -1;
1043 BOOL ScDocument::SearchAndReplace(const SvxSearchItem& rSearchItem,
1044 SCCOL& rCol, SCROW& rRow, SCTAB& rTab,
1045 ScMarkData& rMark,
1046 String& rUndoStr, ScDocument* pUndoDoc)
1048 //! getrennte Markierungen pro Tabelle verwalten !!!!!!!!!!!!!
1050 rMark.MarkToMulti();
1052 BOOL bFound = FALSE;
1053 if (VALIDTAB(rTab))
1055 SCCOL nCol;
1056 SCROW nRow;
1057 SCTAB nTab;
1058 USHORT nCommand = rSearchItem.GetCommand();
1059 if ( nCommand == SVX_SEARCHCMD_FIND_ALL ||
1060 nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1062 for (nTab = 0; nTab <= MAXTAB; nTab++)
1063 if (pTab[nTab])
1065 if (rMark.GetTableSelect(nTab))
1067 nCol = 0;
1068 nRow = 0;
1069 bFound |= pTab[nTab]->SearchAndReplace(
1070 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
1074 // Markierung wird innen schon komplett gesetzt
1076 else
1078 nCol = rCol;
1079 nRow = rRow;
1080 if (rSearchItem.GetBackward())
1082 for (nTab = rTab; ((SCsTAB)nTab >= 0) && !bFound; nTab--)
1083 if (pTab[nTab])
1085 if (rMark.GetTableSelect(nTab))
1087 bFound = pTab[nTab]->SearchAndReplace(
1088 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
1089 if (bFound)
1091 rCol = nCol;
1092 rRow = nRow;
1093 rTab = nTab;
1095 else
1096 ScDocument::GetSearchAndReplaceStart(
1097 rSearchItem, nCol, nRow );
1101 else
1103 for (nTab = rTab; (nTab <= MAXTAB) && !bFound; nTab++)
1104 if (pTab[nTab])
1106 if (rMark.GetTableSelect(nTab))
1108 bFound = pTab[nTab]->SearchAndReplace(
1109 rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc );
1110 if (bFound)
1112 rCol = nCol;
1113 rRow = nRow;
1114 rTab = nTab;
1116 else
1117 ScDocument::GetSearchAndReplaceStart(
1118 rSearchItem, nCol, nRow );
1124 return bFound;
1127 // Outline anpassen
1129 BOOL ScDocument::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, BOOL bShow )
1131 if ( ValidTab(nTab) && pTab[nTab] )
1132 return pTab[nTab]->UpdateOutlineCol( nStartCol, nEndCol, bShow );
1134 DBG_ERROR("missing tab");
1135 return FALSE;
1138 BOOL ScDocument::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, BOOL bShow )
1140 if ( ValidTab(nTab) && pTab[nTab] )
1141 return pTab[nTab]->UpdateOutlineRow( nStartRow, nEndRow, bShow );
1143 DBG_ERROR("missing tab");
1144 return FALSE;
1147 void ScDocument::Sort(SCTAB nTab, const ScSortParam& rSortParam, BOOL bKeepQuery)
1149 if ( ValidTab(nTab) && pTab[nTab] )
1151 BOOL bOldDisableIdle = IsIdleDisabled();
1152 DisableIdle( TRUE );
1153 pTab[nTab]->Sort(rSortParam, bKeepQuery);
1154 DisableIdle( bOldDisableIdle );
1158 SCSIZE ScDocument::Query(SCTAB nTab, const ScQueryParam& rQueryParam, BOOL bKeepSub)
1160 if ( ValidTab(nTab) && pTab[nTab] )
1161 return pTab[nTab]->Query((ScQueryParam&)rQueryParam, bKeepSub);
1163 DBG_ERROR("missing tab");
1164 return 0;
1168 BOOL ScDocument::ValidQuery( SCROW nRow, SCTAB nTab, const ScQueryParam& rQueryParam, BOOL* pSpecial )
1170 if ( ValidTab(nTab) && pTab[nTab] )
1171 return pTab[nTab]->ValidQuery( nRow, rQueryParam, pSpecial );
1173 DBG_ERROR("missing tab");
1174 return FALSE;
1178 void ScDocument::GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, String& rStr)
1180 if ( ValidTab(nTab) && pTab[nTab] )
1181 pTab[nTab]->GetUpperCellString( nCol, nRow, rStr );
1182 else
1183 rStr.Erase();
1186 BOOL ScDocument::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, ScQueryParam& rQueryParam)
1188 if ( ValidTab(nTab) && pTab[nTab] )
1189 return pTab[nTab]->CreateQueryParam(nCol1, nRow1, nCol2, nRow2, rQueryParam);
1191 DBG_ERROR("missing tab");
1192 return FALSE;
1195 BOOL ScDocument::HasAutoFilter( SCCOL nCurCol, SCROW nCurRow, SCTAB nCurTab )
1197 ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab );
1198 BOOL bHasAutoFilter = ( pDBData != NULL );
1200 if ( pDBData )
1202 if ( pDBData->HasHeader() )
1204 SCCOL nCol;
1205 SCROW nRow;
1206 INT16 nFlag;
1208 ScQueryParam aParam;
1209 pDBData->GetQueryParam( aParam );
1210 nRow = aParam.nRow1;
1212 for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ )
1214 nFlag = ((ScMergeFlagAttr*)
1215 GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))->
1216 GetValue();
1218 if ( (nFlag & SC_MF_AUTO) == 0 )
1219 bHasAutoFilter = FALSE;
1222 else
1223 bHasAutoFilter = FALSE;
1226 return bHasAutoFilter;
1229 BOOL ScDocument::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1230 SCTAB nTab )
1232 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1233 //if (VALIDTAB(nTab))
1234 // if (pTab[nTab])
1235 // return pTab[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1237 //return FALSE;
1240 BOOL ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1241 SCTAB nTab )
1243 return VALIDTAB(nTab) && pTab[nTab] && pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1244 //if (VALIDTAB(nTab))
1245 // if (pTab[nTab])
1246 // return pTab[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1248 //return FALSE;
1251 void ScDocument::UpdateDynamicEndRow(ScDBData& rDBData) const
1253 SCCOL nCol1, nCol2;
1254 SCROW nRow1, nRow2;
1255 SCTAB nTab;
1256 rDBData.GetArea(nTab, nCol1, nRow1, nCol2, nRow2);
1257 SCCOL nCol1a = nCol1, nCol2a = nCol2;
1258 SCROW nRow1a = nRow1, nRow2a = nRow2;
1259 GetDataArea(nTab, nCol1a, nRow1a, nCol2a, nRow2a, false);
1260 rDBData.SetDynamicEndRow(nRow2a);
1264 // GetFilterEntries - Eintraege fuer AutoFilter-Listbox
1267 BOOL ScDocument::GetFilterEntries(
1268 SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, TypedScStrCollection& rStrings, bool& rHasDates)
1270 if ( ValidTab(nTab) && pTab[nTab] && pDBCollection )
1272 ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, FALSE); //!??
1273 if (pDBData)
1275 UpdateDynamicEndRow(*pDBData);
1276 SCTAB nAreaTab;
1277 SCCOL nStartCol;
1278 SCROW nStartRow;
1279 SCCOL nEndCol;
1280 SCROW nEndRow;
1281 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1282 if (pDBData->HasHeader())
1283 ++nStartRow;
1285 ScQueryParam aParam;
1286 pDBData->GetQueryParam( aParam );
1287 nEndRow = aParam.nDynamicEndRow;
1288 rStrings.SetCaseSensitive( aParam.bCaseSens );
1290 // return all filter entries, if a filter condition is connected with a boolean OR
1291 if ( bFilter )
1293 SCSIZE nEntryCount = aParam.GetEntryCount();
1294 for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i )
1296 ScQueryEntry& rEntry = aParam.GetEntry(i);
1297 if ( rEntry.eConnect != SC_AND )
1299 bFilter = false;
1300 break;
1305 if ( bFilter )
1307 pTab[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates );
1309 else
1311 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
1314 return TRUE;
1318 return FALSE;
1322 // GetFilterEntriesArea - Eintraege fuer Filter-Dialog
1325 BOOL ScDocument::GetFilterEntriesArea( SCCOL nCol, SCROW nStartRow, SCROW nEndRow,
1326 SCTAB nTab, TypedScStrCollection& rStrings, bool& rHasDates )
1328 if ( ValidTab(nTab) && pTab[nTab] )
1330 pTab[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
1331 return TRUE;
1334 return FALSE;
1338 // GetDataEntries - Eintraege fuer Auswahlliste-Listbox (keine Zahlen / Formeln)
1341 BOOL ScDocument::GetDataEntries( SCCOL nCol, SCROW nRow, SCTAB nTab,
1342 TypedScStrCollection& rStrings, BOOL bLimit )
1344 if( !bLimit )
1346 /* Try to generate the list from list validation. This part is skipped,
1347 if bLimit==TRUE, because in that case this function is called to get
1348 cell values for auto completion on input. */
1349 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
1350 if( nValidation )
1352 const ScValidationData* pData = GetValidationEntry( nValidation );
1353 if( pData && pData->FillSelectionList( rStrings, ScAddress( nCol, nRow, nTab ) ) )
1354 return TRUE;
1358 return ValidTab(nTab) && pTab[nTab] && pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
1359 //if (ValidTab(nTab) && pTab[nTab])
1360 // return pTab[nTab]->GetDataEntries( nCol, nRow, rStrings, bLimit );
1362 //return FALSE;
1366 // GetFormulaEntries - Eintraege fuer Formel-AutoEingabe
1369 // Funktionen werden als 1 schon vom InputHandler eingefuegt
1370 #define SC_STRTYPE_NAMES 2
1371 #define SC_STRTYPE_DBNAMES 3
1372 #define SC_STRTYPE_HEADERS 4
1374 BOOL ScDocument::GetFormulaEntries( TypedScStrCollection& rStrings )
1376 USHORT i;
1379 // Bereichsnamen
1382 if ( pRangeName )
1384 USHORT nRangeCount = pRangeName->GetCount();
1385 for ( i=0; i<nRangeCount; i++ )
1387 ScRangeData* pData = (*pRangeName)[i];
1388 if (pData)
1390 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_NAMES );
1391 if ( !rStrings.Insert(pNew) )
1392 delete pNew;
1398 // Datenbank-Bereiche
1401 if ( pDBCollection )
1403 USHORT nDBCount = pDBCollection->GetCount();
1404 for ( i=0; i<nDBCount; i++ )
1406 ScDBData* pData = (*pDBCollection)[i];
1407 if (pData)
1409 TypedStrData* pNew = new TypedStrData( pData->GetName(), 0.0, SC_STRTYPE_DBNAMES );
1410 if ( !rStrings.Insert(pNew) )
1411 delete pNew;
1417 // Inhalte von Beschriftungsbereichen
1420 ScRangePairList* pLists[2];
1421 pLists[0] = GetColNameRanges();
1422 pLists[1] = GetRowNameRanges();
1423 for (USHORT nListNo=0; nListNo<2; nListNo++)
1425 ScRangePairList* pList = pLists[nListNo];
1426 if (pList)
1427 for ( ScRangePair* pPair = pList->First(); pPair; pPair = pList->Next() )
1429 ScRange aRange = pPair->GetRange(0);
1430 ScCellIterator aIter( this, aRange );
1431 for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() )
1432 if ( pCell->HasStringData() )
1434 String aStr = pCell->GetStringData();
1435 TypedStrData* pNew = new TypedStrData( aStr, 0.0, SC_STRTYPE_HEADERS );
1436 if ( !rStrings.Insert(pNew) )
1437 delete pNew;
1442 return TRUE;
1446 BOOL ScDocument::IsEmbedded() const
1448 return bIsEmbedded;
1451 void ScDocument::GetEmbedded( ScRange& rRange ) const
1453 rRange = aEmbedRange;
1456 Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm
1458 Rectangle aRect;
1459 ScTable* pTable = pTab[aEmbedRange.aStart.Tab()];
1460 if (!pTable)
1462 DBG_ERROR("GetEmbeddedRect ohne Tabelle");
1464 else
1466 SCCOL i;
1468 for (i=0; i<aEmbedRange.aStart.Col(); i++)
1469 aRect.Left() += pTable->GetColWidth(i);
1470 aRect.Top() += pTable->GetRowHeight( 0, aEmbedRange.aStart.Row() - 1);
1471 aRect.Right() = aRect.Left();
1472 for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++)
1473 aRect.Right() += pTable->GetColWidth(i);
1474 aRect.Bottom() = aRect.Top();
1475 aRect.Bottom() += pTable->GetRowHeight( aEmbedRange.aStart.Row(), aEmbedRange.aEnd.Row());
1477 aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS );
1478 aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS );
1479 aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS );
1480 aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS );
1482 return aRect;
1485 void ScDocument::SetEmbedded( const ScRange& rRange )
1487 bIsEmbedded = TRUE;
1488 aEmbedRange = rRange;
1491 void ScDocument::ResetEmbedded()
1493 bIsEmbedded = FALSE;
1494 aEmbedRange = ScRange();
1497 ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect )
1499 ScTable* pTable = pTab[nTab];
1500 if (!pTable)
1502 DBG_ERROR("GetRange ohne Tabelle");
1503 return ScRange();
1506 Rectangle aPosRect = rMMRect;
1507 if ( IsNegativePage( nTab ) )
1508 ScDrawLayer::MirrorRectRTL( aPosRect ); // always with positive (LTR) values
1510 long nSize;
1511 long nTwips;
1512 long nAdd;
1513 BOOL bEnd;
1515 nSize = 0;
1516 nTwips = (long) (aPosRect.Left() / HMM_PER_TWIPS);
1518 SCCOL nX1 = 0;
1519 bEnd = FALSE;
1520 while (!bEnd)
1522 nAdd = (long) pTable->GetColWidth(nX1);
1523 if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL)
1525 nSize += nAdd;
1526 ++nX1;
1528 else
1529 bEnd = TRUE;
1532 nTwips = (long) (aPosRect.Right() / HMM_PER_TWIPS);
1534 SCCOL nX2 = nX1;
1535 bEnd = FALSE;
1536 while (!bEnd)
1538 nAdd = (long) pTable->GetColWidth(nX2);
1539 if (nSize+nAdd < nTwips && nX2<MAXCOL)
1541 nSize += nAdd;
1542 ++nX2;
1544 else
1545 bEnd = TRUE;
1549 nSize = 0;
1550 nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS);
1552 SCROW nY1 = 0;
1553 bEnd = FALSE;
1554 for (SCROW i = nY1; i <= MAXROW && !bEnd; ++i)
1556 if (pTable->RowHidden(i))
1557 continue;
1559 nY1 = i;
1560 nAdd = static_cast<long>(pTable->GetRowHeight(i));
1561 if (nSize+nAdd <= nTwips+1 && nY1<MAXROW)
1563 nSize += nAdd;
1564 ++nY1;
1566 else
1567 bEnd = TRUE;
1569 if (!bEnd)
1570 nY1 = MAXROW; // all hidden down to the bottom
1572 nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS);
1574 SCROW nY2 = nY1;
1575 bEnd = FALSE;
1576 for (SCROW i = nY2; i <= MAXROW && !bEnd; ++i)
1578 nY2 = i;
1579 nAdd = static_cast<long>(pTable->GetRowHeight(i));
1580 if (nSize+nAdd < nTwips && nY2<MAXROW)
1582 nSize += nAdd;
1583 ++nY2;
1585 else
1586 bEnd = TRUE;
1588 if (!bEnd)
1589 nY2 = MAXROW; // all hidden down to the bottom
1591 return ScRange( nX1,nY1,nTab, nX2,nY2,nTab );
1594 void ScDocument::SetEmbedded( const Rectangle& rRect ) // aus VisArea (1/100 mm)
1596 bIsEmbedded = TRUE;
1597 aEmbedRange = GetRange( nVisibleTab, rRect );
1600 // VisArea auf Zellgrenzen anpassen
1602 void lcl_SnapHor( ScTable* pTable, long& rVal, SCCOL& rStartCol )
1604 SCCOL nCol = 0;
1605 long nTwips = (long) (rVal / HMM_PER_TWIPS);
1606 long nSnap = 0;
1607 while ( nCol<MAXCOL )
1609 long nAdd = pTable->GetColWidth(nCol);
1610 if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol )
1612 nSnap += nAdd;
1613 ++nCol;
1615 else
1616 break;
1618 rVal = (long) ( nSnap * HMM_PER_TWIPS );
1619 rStartCol = nCol;
1622 void lcl_SnapVer( ScTable* pTable, long& rVal, SCROW& rStartRow )
1624 SCROW nRow = 0;
1625 long nTwips = (long) (rVal / HMM_PER_TWIPS);
1626 long nSnap = 0;
1628 bool bFound = false;
1629 for (SCROW i = nRow; i <= MAXROW; ++i)
1631 SCROW nLastRow;
1632 if (pTable->RowHidden(i, NULL, &nLastRow))
1634 i = nLastRow;
1635 continue;
1638 nRow = i;
1639 long nAdd = pTable->GetRowHeight(i);
1640 if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow )
1642 nSnap += nAdd;
1643 ++nRow;
1645 else
1647 bFound = true;
1648 break;
1651 if (!bFound)
1652 nRow = MAXROW; // all hidden down to the bottom
1654 rVal = (long) ( nSnap * HMM_PER_TWIPS );
1655 rStartRow = nRow;
1658 void ScDocument::SnapVisArea( Rectangle& rRect ) const
1660 ScTable* pTable = pTab[nVisibleTab];
1661 if (!pTable)
1663 DBG_ERROR("SetEmbedded ohne Tabelle");
1664 return;
1667 BOOL bNegativePage = IsNegativePage( nVisibleTab );
1668 if ( bNegativePage )
1669 ScDrawLayer::MirrorRectRTL( rRect ); // calculate with positive (LTR) values
1671 SCCOL nCol = 0;
1672 lcl_SnapHor( pTable, rRect.Left(), nCol );
1673 ++nCol; // mindestens eine Spalte
1674 lcl_SnapHor( pTable, rRect.Right(), nCol );
1676 SCROW nRow = 0;
1677 lcl_SnapVer( pTable, rRect.Top(), nRow );
1678 ++nRow; // mindestens eine Zeile
1679 lcl_SnapVer( pTable, rRect.Bottom(), nRow );
1681 if ( bNegativePage )
1682 ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle
1685 ScDocProtection* ScDocument::GetDocProtection() const
1687 return pDocProtection.get();
1690 void ScDocument::SetDocProtection(const ScDocProtection* pProtect)
1692 if (pProtect)
1693 pDocProtection.reset(new ScDocProtection(*pProtect));
1694 else
1695 pDocProtection.reset(NULL);
1698 BOOL ScDocument::IsDocProtected() const
1700 return pDocProtection.get() && pDocProtection->isProtected();
1703 BOOL ScDocument::IsDocEditable() const
1705 // import into read-only document is possible
1706 return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
1709 BOOL ScDocument::IsTabProtected( SCTAB nTab ) const
1711 if (VALIDTAB(nTab) && pTab[nTab])
1712 return pTab[nTab]->IsProtected();
1714 DBG_ERROR("Falsche Tabellennummer");
1715 return FALSE;
1718 ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const
1720 if (VALIDTAB(nTab) && pTab[nTab])
1721 return pTab[nTab]->GetProtection();
1723 return NULL;
1726 void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect)
1728 if (!ValidTab(nTab))
1729 return;
1731 pTab[nTab]->SetProtection(pProtect);
1734 void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest)
1736 if (!ValidTab(nTabSrc) || !ValidTab(nTabDest))
1737 return;
1739 pTab[nTabDest]->SetProtection( pTab[nTabSrc]->GetProtection() );
1742 const ScDocOptions& ScDocument::GetDocOptions() const
1744 DBG_ASSERT( pDocOptions, "No DocOptions! :-(" );
1745 return *pDocOptions;
1748 void ScDocument::SetDocOptions( const ScDocOptions& rOpt )
1750 DBG_ASSERT( pDocOptions, "No DocOptions! :-(" );
1751 *pDocOptions = rOpt;
1753 xPoolHelper->SetFormTableOpt(rOpt);
1755 SetGrammar( rOpt.GetFormulaSyntax() );
1757 // Update the separators.
1758 ScCompiler::UpdateSeparatorsNative(
1759 rOpt.GetFormulaSepArg(), rOpt.GetFormulaSepArrayCol(), rOpt.GetFormulaSepArrayRow());
1762 const ScViewOptions& ScDocument::GetViewOptions() const
1764 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
1765 return *pViewOptions;
1768 void ScDocument::SetViewOptions( const ScViewOptions& rOpt )
1770 DBG_ASSERT( pViewOptions, "No ViewOptions! :-(" );
1771 *pViewOptions = rOpt;
1774 void ScDocument::GetLanguage( LanguageType& rLatin, LanguageType& rCjk, LanguageType& rCtl ) const
1776 rLatin = eLanguage;
1777 rCjk = eCjkLanguage;
1778 rCtl = eCtlLanguage;
1781 void ScDocument::SetLanguage( LanguageType eLatin, LanguageType eCjk, LanguageType eCtl )
1783 eLanguage = eLatin;
1784 eCjkLanguage = eCjk;
1785 eCtlLanguage = eCtl;
1786 if ( xPoolHelper.isValid() )
1788 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
1789 pPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) );
1790 pPool->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage, ATTR_CJK_FONT_LANGUAGE ) );
1791 pPool->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage, ATTR_CTL_FONT_LANGUAGE ) );
1794 UpdateDrawLanguages(); // set edit engine defaults in drawing layer pool
1797 void ScDocument::SetDrawDefaults()
1799 bSetDrawDefaults = TRUE;
1800 UpdateDrawDefaults();
1803 Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow,
1804 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
1806 if (!ValidTab(nTab) || !pTab[nTab])
1808 DBG_ERROR("GetMMRect: falsche Tabelle");
1809 return Rectangle(0,0,0,0);
1812 SCCOL i;
1813 Rectangle aRect;
1815 for (i=0; i<nStartCol; i++)
1816 aRect.Left() += GetColWidth(i,nTab);
1817 aRect.Top() += FastGetRowHeight( 0, nStartRow-1, nTab);
1819 aRect.Right() = aRect.Left();
1820 aRect.Bottom() = aRect.Top();
1822 for (i=nStartCol; i<=nEndCol; i++)
1823 aRect.Right() += GetColWidth(i,nTab);
1824 aRect.Bottom() += FastGetRowHeight( nStartRow, nEndRow, nTab);
1826 aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS);
1827 aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS);
1828 aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS);
1829 aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS);
1831 if ( IsNegativePage( nTab ) )
1832 ScDrawLayer::MirrorRectRTL( aRect );
1834 return aRect;
1837 void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions )
1839 delete pExtDocOptions;
1840 pExtDocOptions = pNewOptions;
1843 void ScDocument::DoMergeContents( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1844 SCCOL nEndCol, SCROW nEndRow )
1846 String aEmpty;
1847 String aTotal;
1848 String aCellStr;
1849 SCCOL nCol;
1850 SCROW nRow;
1851 for (nRow=nStartRow; nRow<=nEndRow; nRow++)
1852 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
1854 GetString(nCol,nRow,nTab,aCellStr);
1855 if (aCellStr.Len())
1857 if (aTotal.Len())
1858 aTotal += ' ';
1859 aTotal += aCellStr;
1861 if (nCol != nStartCol || nRow != nStartRow)
1862 SetString(nCol,nRow,nTab,aEmpty);
1865 SetString(nStartCol,nStartRow,nTab,aTotal);
1868 void ScDocument::DoMerge( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1869 SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions )
1871 ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 );
1872 ApplyAttr( nStartCol, nStartRow, nTab, aAttr );
1874 if ( nEndCol > nStartCol )
1875 ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR );
1876 if ( nEndRow > nStartRow )
1877 ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER );
1878 if ( nEndCol > nStartCol && nEndRow > nStartRow )
1879 ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1881 // remove all covered notes (removed captions are collected by drawing undo if active)
1882 USHORT nDelFlag = IDF_NOTE | (bDeleteCaptions ? 0 : IDF_NOCAPTIONS);
1883 if( nStartCol < nEndCol )
1884 DeleteAreaTab( nStartCol + 1, nStartRow, nEndCol, nStartRow, nTab, nDelFlag );
1885 if( nStartRow < nEndRow )
1886 DeleteAreaTab( nStartCol, nStartRow + 1, nEndCol, nEndRow, nTab, nDelFlag );
1889 void ScDocument::RemoveMerge( SCCOL nCol, SCROW nRow, SCTAB nTab )
1891 const ScMergeAttr* pAttr = (const ScMergeAttr*)
1892 GetAttr( nCol, nRow, nTab, ATTR_MERGE );
1894 if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 )
1895 return;
1897 SCCOL nEndCol = nCol + pAttr->GetColMerge() - 1;
1898 SCROW nEndRow = nRow + pAttr->GetRowMerge() - 1;
1900 RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1902 const ScMergeAttr* pDefAttr = (const ScMergeAttr*)
1903 &xPoolHelper->GetDocPool()->GetDefaultItem( ATTR_MERGE );
1904 ApplyAttr( nCol, nRow, nTab, *pDefAttr );
1907 void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab,
1908 SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow )
1910 if ( ValidTab(nTab) && pTab[nTab] )
1911 pTab[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow );
1914 void ScDocument::IncSizeRecalcLevel( SCTAB nTab )
1916 if ( ValidTab(nTab) && pTab[nTab] )
1917 pTab[nTab]->IncRecalcLevel();
1920 void ScDocument::DecSizeRecalcLevel( SCTAB nTab )
1922 if ( ValidTab(nTab) && pTab[nTab] )
1923 pTab[nTab]->DecRecalcLevel();