fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / data / documen3.cxx
blobda216f2a3379588326c02e3ac0f228d7c9954dae
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
21 #include "scitems.hxx"
22 #include <editeng/langitem.hxx>
23 #include <svl/srchitem.hxx>
24 #include <sfx2/linkmgr.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <sfx2/objsh.hxx>
27 #include <svl/zforlist.hxx>
28 #include <svl/PasswordHelper.hxx>
29 #include <vcl/svapp.hxx>
30 #include "document.hxx"
31 #include "attrib.hxx"
32 #include "table.hxx"
33 #include "rangenam.hxx"
34 #include "dbdata.hxx"
35 #include "pivot.hxx"
36 #include "docpool.hxx"
37 #include "poolhelp.hxx"
38 #include "autoform.hxx"
39 #include "rangelst.hxx"
40 #include "chartarr.hxx"
41 #include "chartlock.hxx"
42 #include "refupdat.hxx"
43 #include "docoptio.hxx"
44 #include "viewopti.hxx"
45 #include "scextopt.hxx"
46 #include "brdcst.hxx"
47 #include "bcaslot.hxx"
48 #include "tablink.hxx"
49 #include "externalrefmgr.hxx"
50 #include "markdata.hxx"
51 #include "validat.hxx"
52 #include "dociter.hxx"
53 #include "detdata.hxx"
54 #include "detfunc.hxx"
55 #include "inputopt.hxx"
56 #include "chartlis.hxx"
57 #include "sc.hrc"
58 #include "hints.hxx"
59 #include "dpobject.hxx"
60 #include "drwlayer.hxx"
61 #include "unoreflist.hxx"
62 #include "listenercalls.hxx"
63 #include "dpshttab.hxx"
64 #include "dpcache.hxx"
65 #include "tabprotection.hxx"
66 #include "formulaparserpool.hxx"
67 #include "clipparam.hxx"
68 #include "sheetevents.hxx"
69 #include "colorscale.hxx"
70 #include "queryentry.hxx"
71 #include "formulacell.hxx"
72 #include "refupdatecontext.hxx"
73 #include "scopetools.hxx"
75 #include "globalnames.hxx"
76 #include <boost/scoped_ptr.hpp>
77 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
79 using namespace com::sun::star;
81 namespace {
83 void sortAndRemoveDuplicates(std::vector<ScTypedStrData>& rStrings, bool bCaseSens)
85 if (bCaseSens)
87 std::sort(rStrings.begin(), rStrings.end(), ScTypedStrData::LessCaseSensitive());
88 std::vector<ScTypedStrData>::iterator it =
89 std::unique(rStrings.begin(), rStrings.end(), ScTypedStrData::EqualCaseSensitive());
90 rStrings.erase(it, rStrings.end());
92 else
94 std::sort(rStrings.begin(), rStrings.end(), ScTypedStrData::LessCaseInsensitive());
95 std::vector<ScTypedStrData>::iterator it =
96 std::unique(rStrings.begin(), rStrings.end(), ScTypedStrData::EqualCaseInsensitive());
97 rStrings.erase(it, rStrings.end());
103 void ScDocument::GetAllTabRangeNames(ScRangeName::TabNameCopyMap& rNames) const
105 ScRangeName::TabNameCopyMap aNames;
106 for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); ++i)
108 if (!maTabs[i])
109 // no more tables to iterate through.
110 break;
112 const ScRangeName* p = maTabs[i]->mpRangeName;
113 if (!p || p->empty())
114 // ignore empty ones.
115 continue;
117 aNames.insert(ScRangeName::TabNameCopyMap::value_type(i, p));
119 rNames.swap(aNames);
122 void ScDocument::SetAllRangeNames( const boost::ptr_map<OUString, ScRangeName>& rRangeMap)
124 OUString aGlobalStr(STR_GLOBAL_RANGE_NAME);
125 boost::ptr_map<OUString,ScRangeName>::const_iterator itr = rRangeMap.begin(), itrEnd = rRangeMap.end();
126 for (; itr!=itrEnd; ++itr)
128 if (itr->first == aGlobalStr)
130 delete pRangeName;
131 const ScRangeName* pName = itr->second;
132 if (pName->empty())
133 pRangeName = NULL;
134 else
135 pRangeName = new ScRangeName( *pName );
137 else
139 const ScRangeName* pName = itr->second;
140 SCTAB nTab;
141 bool bFound = GetTable(itr->first, nTab);
142 assert(bFound); (void)bFound; // fouled up?
143 if (pName->empty())
144 SetRangeName( nTab, NULL );
145 else
146 SetRangeName( nTab, new ScRangeName( *pName ) );
151 void ScDocument::GetTabRangeNameMap(std::map<OUString, ScRangeName*>& aRangeNameMap)
153 for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); ++i)
155 if (!maTabs[i])
156 continue;
157 ScRangeName* p = maTabs[i]->GetRangeName();
158 if (!p )
160 p = new ScRangeName();
161 SetRangeName(i, p);
163 OUString aTableName;
164 maTabs[i]->GetName(aTableName);
165 aRangeNameMap.insert(std::pair<OUString, ScRangeName*>(aTableName,p));
169 void ScDocument::GetRangeNameMap(std::map<OUString, ScRangeName*>& aRangeNameMap)
171 GetTabRangeNameMap(aRangeNameMap);
172 if (!pRangeName)
174 pRangeName = new ScRangeName();
176 OUString aGlobal(STR_GLOBAL_RANGE_NAME);
177 aRangeNameMap.insert(std::pair<OUString, ScRangeName*>(aGlobal, pRangeName));
180 ScRangeName* ScDocument::GetRangeName(SCTAB nTab) const
182 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
183 return NULL;
185 return maTabs[nTab]->GetRangeName();
188 ScRangeName* ScDocument::GetRangeName() const
190 if (!pRangeName)
191 pRangeName = new ScRangeName;
192 return pRangeName;
195 void ScDocument::SetRangeName(SCTAB nTab, ScRangeName* pNew)
197 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
198 return;
200 return maTabs[nTab]->SetRangeName(pNew);
203 void ScDocument::SetRangeName( ScRangeName* pNewRangeName )
205 if (pRangeName == pNewRangeName)
206 return;
208 delete pRangeName;
209 pRangeName = pNewRangeName;
212 bool ScDocument::InsertNewRangeName( const OUString& rName, const ScAddress& rPos, const OUString& rExpr )
214 ScRangeName* pGlobalNames = GetRangeName();
215 if (!pGlobalNames)
216 return false;
218 ScRangeData* pName = new ScRangeData(this, rName, rExpr, rPos, RT_NAME, GetGrammar());
219 return pGlobalNames->insert(pName);
222 const ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, OUString* pName ) const
224 const ScRangeData* pData = NULL;
225 if ( pRangeName )
227 pData = pRangeName->findByRange( rBlock );
228 if (pData && pName)
229 *pName = pData->GetName();
231 return pData;
234 void ScDocument::SetDBCollection( ScDBCollection* pNewDBCollection, bool bRemoveAutoFilter )
236 if (pDBCollection && bRemoveAutoFilter)
238 // remove auto filter attribute if new db data don't contain auto filter flag
239 // start position is also compared, so bRemoveAutoFilter must not be set from ref-undo!
241 ScDBCollection::NamedDBs& rNamedDBs = pDBCollection->getNamedDBs();
242 ScDBCollection::NamedDBs::const_iterator itr = rNamedDBs.begin(), itrEnd = rNamedDBs.end();
243 for (; itr != itrEnd; ++itr)
245 const ScDBData& rOldData = *itr;
246 if (!rOldData.HasAutoFilter())
247 continue;
249 ScRange aOldRange;
250 rOldData.GetArea(aOldRange);
252 bool bFound = false;
253 if (pNewDBCollection)
255 ScDBData* pNewData = pNewDBCollection->getNamedDBs().findByUpperName(rOldData.GetUpperName());
256 if (pNewData)
258 if (pNewData->HasAutoFilter())
260 ScRange aNewRange;
261 pNewData->GetArea(aNewRange);
262 if (aOldRange.aStart == aNewRange.aStart)
263 bFound = true;
268 if (!bFound)
270 aOldRange.aEnd.SetRow(aOldRange.aStart.Row());
271 RemoveFlagsTab( aOldRange.aStart.Col(), aOldRange.aStart.Row(),
272 aOldRange.aEnd.Col(), aOldRange.aEnd.Row(),
273 aOldRange.aStart.Tab(), SC_MF_AUTO );
274 RepaintRange( aOldRange );
279 delete pDBCollection;
281 pDBCollection = pNewDBCollection;
284 const ScDBData* ScDocument::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
286 if (pDBCollection)
287 return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly);
288 else
289 return NULL;
292 ScDBData* ScDocument::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly)
294 if (pDBCollection)
295 return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly);
296 else
297 return NULL;
300 const ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
302 if (pDBCollection)
303 return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2);
304 else
305 return NULL;
308 ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
310 if (pDBCollection)
311 return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2);
312 else
313 return NULL;
316 bool ScDocument::HasPivotTable() const
318 return pDPCollection && pDPCollection->GetCount();
321 ScDPCollection* ScDocument::GetDPCollection()
323 if (!pDPCollection)
324 pDPCollection = new ScDPCollection(this);
325 return pDPCollection;
328 const ScDPCollection* ScDocument::GetDPCollection() const
330 return pDPCollection;
333 ScDPObject* ScDocument::GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
335 if (!pDPCollection)
336 return NULL;
338 sal_uInt16 nCount = pDPCollection->GetCount();
339 ScAddress aPos( nCol, nRow, nTab );
340 for (sal_uInt16 i=0; i<nCount; i++)
341 if ( (*pDPCollection)[i]->GetOutRange().In( aPos ) )
342 return (*pDPCollection)[i];
344 return NULL;
347 ScDPObject* ScDocument::GetDPAtBlock( const ScRange & rBlock ) const
349 if (!pDPCollection)
350 return NULL;
352 /* Walk the collection in reverse order to get something of an
353 * approximation of MS Excels 'most recent' effect. */
354 sal_uInt16 i = pDPCollection->GetCount();
355 while ( i-- > 0 )
356 if ( (*pDPCollection)[i]->GetOutRange().In( rBlock ) )
357 return (*pDPCollection)[i];
359 return NULL;
362 void ScDocument::StopTemporaryChartLock()
364 if( apTemporaryChartLock.get() )
365 apTemporaryChartLock->StopLocking();
368 void ScDocument::SetChartListenerCollection(
369 ScChartListenerCollection* pNewChartListenerCollection,
370 bool bSetChartRangeLists )
372 ScChartListenerCollection* pOld = pChartListenerCollection;
373 pChartListenerCollection = pNewChartListenerCollection;
374 if ( pChartListenerCollection )
376 if ( pOld )
377 pChartListenerCollection->SetDiffDirty( *pOld, bSetChartRangeLists );
378 pChartListenerCollection->StartAllListeners();
380 delete pOld;
383 void ScDocument::SetScenario( SCTAB nTab, bool bFlag )
385 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
386 maTabs[nTab]->SetScenario(bFlag);
389 bool ScDocument::IsScenario( SCTAB nTab ) const
391 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] &&maTabs[nTab]->IsScenario();
394 void ScDocument::SetScenarioData( SCTAB nTab, const OUString& rComment,
395 const Color& rColor, sal_uInt16 nFlags )
397 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario())
399 maTabs[nTab]->SetScenarioComment( rComment );
400 maTabs[nTab]->SetScenarioColor( rColor );
401 maTabs[nTab]->SetScenarioFlags( nFlags );
405 Color ScDocument::GetTabBgColor( SCTAB nTab ) const
407 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
408 return maTabs[nTab]->GetTabBgColor();
409 return Color(COL_AUTO);
412 void ScDocument::SetTabBgColor( SCTAB nTab, const Color& rColor )
414 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
415 maTabs[nTab]->SetTabBgColor(rColor);
418 bool ScDocument::IsDefaultTabBgColor( SCTAB nTab ) const
420 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
421 return maTabs[nTab]->GetTabBgColor() == COL_AUTO;
422 return true;
425 void ScDocument::GetScenarioData( SCTAB nTab, OUString& rComment,
426 Color& rColor, sal_uInt16& rFlags ) const
428 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario())
430 maTabs[nTab]->GetScenarioComment( rComment );
431 rColor = maTabs[nTab]->GetScenarioColor();
432 rFlags = maTabs[nTab]->GetScenarioFlags();
436 void ScDocument::GetScenarioFlags( SCTAB nTab, sal_uInt16& rFlags ) const
438 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario())
439 rFlags = maTabs[nTab]->GetScenarioFlags();
442 bool ScDocument::IsLinked( SCTAB nTab ) const
444 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsLinked();
445 // euqivalent to
446 //if (ValidTab(nTab) && pTab[nTab])
447 // return pTab[nTab]->IsLinked();
448 //return false;
451 formula::FormulaGrammar::AddressConvention ScDocument::GetAddressConvention() const
453 return formula::FormulaGrammar::extractRefConvention(eGrammar);
456 void ScDocument::SetGrammar( formula::FormulaGrammar::Grammar eGram )
458 eGrammar = eGram;
461 sal_uInt8 ScDocument::GetLinkMode( SCTAB nTab ) const
463 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
464 return maTabs[nTab]->GetLinkMode();
465 return SC_LINK_NONE;
468 const OUString ScDocument::GetLinkDoc( SCTAB nTab ) const
470 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
471 return maTabs[nTab]->GetLinkDoc();
472 return OUString();
475 const OUString ScDocument::GetLinkFlt( SCTAB nTab ) const
477 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
478 return maTabs[nTab]->GetLinkFlt();
479 return OUString();
482 const OUString ScDocument::GetLinkOpt( SCTAB nTab ) const
484 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
485 return maTabs[nTab]->GetLinkOpt();
486 return OUString();
489 const OUString ScDocument::GetLinkTab( SCTAB nTab ) const
491 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
492 return maTabs[nTab]->GetLinkTab();
493 return OUString();
496 sal_uLong ScDocument::GetLinkRefreshDelay( SCTAB nTab ) const
498 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
499 return maTabs[nTab]->GetLinkRefreshDelay();
500 return 0;
503 void ScDocument::SetLink( SCTAB nTab, sal_uInt8 nMode, const OUString& rDoc,
504 const OUString& rFilter, const OUString& rOptions,
505 const OUString& rTabName, sal_uLong nRefreshDelay )
507 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
508 maTabs[nTab]->SetLink( nMode, rDoc, rFilter, rOptions, rTabName, nRefreshDelay );
511 bool ScDocument::HasLink( const OUString& rDoc,
512 const OUString& rFilter, const OUString& rOptions ) const
514 SCTAB nCount = static_cast<SCTAB>(maTabs.size());
515 for (SCTAB i=0; i<nCount; i++)
516 if (maTabs[i]->IsLinked()
517 && maTabs[i]->GetLinkDoc() == rDoc
518 && maTabs[i]->GetLinkFlt() == rFilter
519 && maTabs[i]->GetLinkOpt() == rOptions)
520 return true;
522 return false;
525 bool ScDocument::LinkExternalTab( SCTAB& rTab, const OUString& aDocTab,
526 const OUString& aFileName, const OUString& aTabName )
528 if ( IsClipboard() )
530 OSL_FAIL( "LinkExternalTab in Clipboard" );
531 return false;
533 rTab = 0;
534 OUString aFilterName; // Is filled by the Loader
535 OUString aOptions; // Filter options
536 sal_uInt32 nLinkCnt = pExtDocOptions ? pExtDocOptions->GetDocSettings().mnLinkCnt : 0;
537 ScDocumentLoader aLoader( aFileName, aFilterName, aOptions, nLinkCnt + 1 );
538 if ( aLoader.IsError() )
539 return false;
540 ScDocument* pSrcDoc = aLoader.GetDocument();
542 // Copy table
543 SCTAB nSrcTab;
544 if ( pSrcDoc->GetTable( aTabName, nSrcTab ) )
546 if ( !InsertTab( SC_TAB_APPEND, aDocTab, true ) )
548 OSL_FAIL("can't insert external document table");
549 return false;
551 rTab = GetTableCount() - 1;
552 // Don't insert anew, just the results
553 TransferTab( pSrcDoc, nSrcTab, rTab, false, true );
555 else
556 return false;
558 sal_uLong nRefreshDelay = 0;
560 bool bWasThere = HasLink( aFileName, aFilterName, aOptions );
561 SetLink( rTab, SC_LINK_VALUE, aFileName, aFilterName, aOptions, aTabName, nRefreshDelay );
562 if ( !bWasThere ) // Add link only once per source document
564 ScTableLink* pLink = new ScTableLink( pShell, aFileName, aFilterName, aOptions, nRefreshDelay );
565 pLink->SetInCreate( true );
566 OUString aFilName = aFilterName;
567 GetLinkManager()->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, OUString(aFileName),
568 &aFilName );
569 pLink->Update();
570 pLink->SetInCreate( false );
571 SfxBindings* pBindings = GetViewBindings();
572 if (pBindings)
573 pBindings->Invalidate( SID_LINKS );
575 return true;
578 ScExternalRefManager* ScDocument::GetExternalRefManager() const
580 ScDocument* pThis = const_cast<ScDocument*>(this);
581 if (!pExternalRefMgr.get())
582 pThis->pExternalRefMgr.reset( new ScExternalRefManager( pThis));
584 return pExternalRefMgr.get();
587 bool ScDocument::IsInExternalReferenceMarking() const
589 return pExternalRefMgr.get() && pExternalRefMgr->isInReferenceMarking();
592 void ScDocument::MarkUsedExternalReferences()
594 if (!pExternalRefMgr.get())
595 return;
596 if (!pExternalRefMgr->hasExternalData())
597 return;
598 // Charts.
599 pExternalRefMgr->markUsedByLinkListeners();
600 // Formula cells.
601 pExternalRefMgr->markUsedExternalRefCells();
603 /* NOTE: Conditional formats and validation objects are marked when
604 * collecting them during export. */
607 ScFormulaParserPool& ScDocument::GetFormulaParserPool() const
609 if( !mxFormulaParserPool.get() )
610 mxFormulaParserPool.reset( new ScFormulaParserPool( *this ) );
611 return *mxFormulaParserPool;
614 const ScSheetEvents* ScDocument::GetSheetEvents( SCTAB nTab ) const
616 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
617 return maTabs[nTab]->GetSheetEvents();
618 return NULL;
621 void ScDocument::SetSheetEvents( SCTAB nTab, const ScSheetEvents* pNew )
623 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
624 maTabs[nTab]->SetSheetEvents( pNew );
627 bool ScDocument::HasSheetEventScript( SCTAB nTab, sal_Int32 nEvent, bool bWithVbaEvents ) const
629 if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
631 // check if any event handler script has been configured
632 const ScSheetEvents* pEvents = maTabs[nTab]->GetSheetEvents();
633 if ( pEvents && pEvents->GetScript( nEvent ) )
634 return true;
635 // check if VBA event handlers exist
636 if (bWithVbaEvents && mxVbaEvents.is()) try
638 uno::Sequence< uno::Any > aArgs( 1 );
639 aArgs[ 0 ] <<= nTab;
640 if (mxVbaEvents->hasVbaEventHandler( ScSheetEvents::GetVbaSheetEventId( nEvent ), aArgs ) ||
641 mxVbaEvents->hasVbaEventHandler( ScSheetEvents::GetVbaDocumentEventId( nEvent ), uno::Sequence< uno::Any >() ))
642 return true;
644 catch( uno::Exception& )
648 return false;
651 bool ScDocument::HasAnySheetEventScript( sal_Int32 nEvent, bool bWithVbaEvents ) const
653 SCTAB nSize = static_cast<SCTAB>(maTabs.size());
654 for (SCTAB nTab = 0; nTab < nSize; nTab++)
655 if (HasSheetEventScript( nTab, nEvent, bWithVbaEvents ))
656 return true;
657 return false;
660 bool ScDocument::HasAnyCalcNotification() const
662 SCTAB nSize = static_cast<SCTAB>(maTabs.size());
663 for (SCTAB nTab = 0; nTab < nSize; nTab++)
664 if (maTabs[nTab] && maTabs[nTab]->GetCalcNotification())
665 return true;
666 return false;
669 bool ScDocument::HasCalcNotification( SCTAB nTab ) const
671 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
672 return maTabs[nTab]->GetCalcNotification();
673 return false;
676 void ScDocument::SetCalcNotification( SCTAB nTab )
678 // set only if not set before
679 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && !maTabs[nTab]->GetCalcNotification())
680 maTabs[nTab]->SetCalcNotification(true);
683 void ScDocument::ResetCalcNotifications()
685 SCTAB nSize = static_cast<SCTAB>(maTabs.size());
686 for (SCTAB nTab = 0; nTab < nSize; nTab++)
687 if (maTabs[nTab] && maTabs[nTab]->GetCalcNotification())
688 maTabs[nTab]->SetCalcNotification(false);
691 ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, bool bCreate )
693 ScOutlineTable* pVal = NULL;
695 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
696 if (maTabs[nTab])
698 pVal = maTabs[nTab]->GetOutlineTable();
699 if (!pVal)
700 if (bCreate)
702 maTabs[nTab]->StartOutlineTable();
703 pVal = maTabs[nTab]->GetOutlineTable();
707 return pVal;
710 bool ScDocument::SetOutlineTable( SCTAB nTab, const ScOutlineTable* pNewOutline )
712 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->SetOutlineTable(pNewOutline);
715 void ScDocument::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow,
716 SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
718 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
719 maTabs[nTab]->DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
722 bool ScDocument::TestRemoveSubTotals( SCTAB nTab, const ScSubTotalParam& rParam )
724 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->TestRemoveSubTotals( rParam );
727 void ScDocument::RemoveSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
729 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
730 maTabs[nTab]->RemoveSubTotals( rParam );
733 bool ScDocument::DoSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
735 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->DoSubTotals( rParam );
738 bool ScDocument::HasSubTotalCells( const ScRange& rRange )
740 ScCellIterator aIter( this, rRange );
741 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
743 if (aIter.getType() != CELLTYPE_FORMULA)
744 continue;
746 if (aIter.getFormulaCell()->IsSubTotal())
747 return true;
749 return false; // none found
753 * From this document this method copies the cells of positions at which
754 * there are also cells in pPosDoc to pDestDoc
756 void ScDocument::CopyUpdated( ScDocument* pPosDoc, ScDocument* pDestDoc )
758 SCTAB nCount = static_cast<SCTAB>(maTabs.size());
759 for (SCTAB nTab=0; nTab<nCount; nTab++)
760 if (maTabs[nTab] && pPosDoc->maTabs[nTab] && pDestDoc->maTabs[nTab])
761 maTabs[nTab]->CopyUpdated( pPosDoc->maTabs[nTab], pDestDoc->maTabs[nTab] );
764 void ScDocument::CopyScenario( SCTAB nSrcTab, SCTAB nDestTab, bool bNewScenario )
766 if (ValidTab(nSrcTab) && ValidTab(nDestTab) && nSrcTab < static_cast<SCTAB>(maTabs.size())
767 && nDestTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab] && maTabs[nDestTab])
769 // Set flags correctly for active scenarios
770 // and write current values back to recently active scenarios
771 ScRangeList aRanges = *maTabs[nSrcTab]->GetScenarioRanges();
773 // nDestTab is the target table
774 for ( SCTAB nTab = nDestTab+1;
775 nTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario();
776 nTab++ )
778 if ( maTabs[nTab]->IsActiveScenario() ) // Even if it's the same scenario
780 bool bTouched = false;
781 for ( size_t nR=0, nRangeCount = aRanges.size(); nR < nRangeCount && !bTouched; nR++ )
783 const ScRange* pRange = aRanges[ nR ];
784 if ( maTabs[nTab]->HasScenarioRange( *pRange ) )
785 bTouched = true;
787 if (bTouched)
789 maTabs[nTab]->SetActiveScenario(false);
790 if ( maTabs[nTab]->GetScenarioFlags() & SC_SCENARIO_TWOWAY )
791 maTabs[nTab]->CopyScenarioFrom( maTabs[nDestTab] );
796 maTabs[nSrcTab]->SetActiveScenario(true); // This is where it's from ...
797 if (!bNewScenario) // Copy data from the selected scenario
799 sc::AutoCalcSwitch aACSwitch(*this, false);
800 maTabs[nSrcTab]->CopyScenarioTo( maTabs[nDestTab] );
802 sc::SetFormulaDirtyContext aCxt;
803 SetAllFormulasDirty(aCxt);
808 void ScDocument::MarkScenario( SCTAB nSrcTab, SCTAB nDestTab, ScMarkData& rDestMark,
809 bool bResetMark, sal_uInt16 nNeededBits ) const
811 if (bResetMark)
812 rDestMark.ResetMark();
814 if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab])
815 maTabs[nSrcTab]->MarkScenarioIn( rDestMark, nNeededBits );
817 rDestMark.SetAreaTab( nDestTab );
820 bool ScDocument::HasScenarioRange( SCTAB nTab, const ScRange& rRange ) const
822 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->HasScenarioRange( rRange );
825 const ScRangeList* ScDocument::GetScenarioRanges( SCTAB nTab ) const
827 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
828 return maTabs[nTab]->GetScenarioRanges();
830 return NULL;
833 bool ScDocument::IsActiveScenario( SCTAB nTab ) const
835 return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsActiveScenario( );
838 void ScDocument::SetActiveScenario( SCTAB nTab, bool bActive )
840 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
841 maTabs[nTab]->SetActiveScenario( bActive );
844 bool ScDocument::TestCopyScenario( SCTAB nSrcTab, SCTAB nDestTab ) const
846 if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size())
847 && nDestTab < static_cast<SCTAB>(maTabs.size())&& ValidTab(nDestTab))
848 return maTabs[nSrcTab]->TestCopyScenarioTo( maTabs[nDestTab] );
850 OSL_FAIL("wrong table at TestCopyScenario");
851 return false;
854 void ScDocument::AddUnoObject( SfxListener& rObject )
856 if (!pUnoBroadcaster)
857 pUnoBroadcaster = new SfxBroadcaster;
859 rObject.StartListening( *pUnoBroadcaster );
862 void ScDocument::RemoveUnoObject( SfxListener& rObject )
864 if (pUnoBroadcaster)
866 rObject.EndListening( *pUnoBroadcaster );
868 if ( bInUnoBroadcast )
870 // Broadcasts from ScDocument::BroadcastUno are the only way that
871 // uno object methods are called without holding a reference.
873 // If RemoveUnoObject is called from an object dtor in the finalizer thread
874 // while the main thread is calling BroadcastUno, the dtor thread must wait
875 // (or the object's Notify might try to access a deleted object).
876 // The SolarMutex can't be locked here because if a component is called from
877 // a VCL event, the main thread has the SolarMutex locked all the time.
879 // This check is done after calling EndListening, so a later BroadcastUno call
880 // won't touch this object.
882 vcl::SolarMutexTryAndBuyGuard g;
883 if (g.isAcquired())
885 // BroadcastUno is always called with the SolarMutex locked, so if it
886 // can be acquired, this is within the same thread (should not happen)
887 OSL_FAIL( "RemoveUnoObject called from BroadcastUno" );
889 else
891 // Let the thread that called BroadcastUno continue
892 while ( bInUnoBroadcast )
894 osl::Thread::yield();
899 else
901 OSL_FAIL("No Uno broadcaster");
905 void ScDocument::BroadcastUno( const SfxHint &rHint )
907 if (pUnoBroadcaster)
909 bInUnoBroadcast = true;
910 pUnoBroadcaster->Broadcast( rHint );
911 bInUnoBroadcast = false;
913 // During Broadcast notification, Uno objects can add to pUnoListenerCalls.
914 // The listener calls must be processed after completing the broadcast,
915 // because they can add or remove objects from pUnoBroadcaster.
917 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
918 if ( pUnoListenerCalls && pSimpleHint &&
919 pSimpleHint->GetId() == SFX_HINT_DATACHANGED &&
920 !bInUnoListenerCall )
922 // Listener calls may lead to BroadcastUno calls again. The listener calls
923 // are not nested, instead the calls are collected in the list, and the
924 // outermost call executes them all.
926 ScChartLockGuard aChartLockGuard(this);
927 bInUnoListenerCall = true;
928 pUnoListenerCalls->ExecuteAndClear();
929 bInUnoListenerCall = false;
934 void ScDocument::AddUnoListenerCall( const uno::Reference<util::XModifyListener>& rListener,
935 const lang::EventObject& rEvent )
937 OSL_ENSURE( bInUnoBroadcast, "AddUnoListenerCall is supposed to be called from BroadcastUno only" );
939 if ( !pUnoListenerCalls )
940 pUnoListenerCalls = new ScUnoListenerCalls;
941 pUnoListenerCalls->Add( rListener, rEvent );
944 void ScDocument::BeginUnoRefUndo()
946 OSL_ENSURE( !pUnoRefUndoList, "BeginUnoRefUndo twice" );
947 delete pUnoRefUndoList;
949 pUnoRefUndoList = new ScUnoRefList;
952 ScUnoRefList* ScDocument::EndUnoRefUndo()
954 ScUnoRefList* pRet = pUnoRefUndoList;
955 pUnoRefUndoList = NULL;
956 return pRet; // Must be deleted by caller!
959 void ScDocument::AddUnoRefChange( sal_Int64 nId, const ScRangeList& rOldRanges )
961 if ( pUnoRefUndoList )
962 pUnoRefUndoList->Add( nId, rOldRanges );
965 void ScDocument::UpdateReference(
966 sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, bool bIncludeDraw, bool bUpdateNoteCaptionPos )
968 if (!ValidRange(rCxt.maRange))
969 return;
971 boost::scoped_ptr<sc::ExpandRefsSwitch> pExpandRefsSwitch;
972 if (rCxt.isInserted())
973 pExpandRefsSwitch.reset(new sc::ExpandRefsSwitch(*this, SC_MOD()->GetInputOptions().GetExpandRefs()));
975 size_t nFirstTab, nLastTab;
976 if (rCxt.meMode == URM_COPY)
978 nFirstTab = rCxt.maRange.aStart.Tab();
979 nLastTab = rCxt.maRange.aEnd.Tab();
981 else
983 // TODO: Have these methods use the context object directly.
984 ScRange aRange = rCxt.maRange;
985 UpdateRefMode eUpdateRefMode = rCxt.meMode;
986 SCCOL nDx = rCxt.mnColDelta;
987 SCROW nDy = rCxt.mnRowDelta;
988 SCTAB nDz = rCxt.mnTabDelta;
989 SCCOL nCol1 = rCxt.maRange.aStart.Col(), nCol2 = rCxt.maRange.aEnd.Col();
990 SCROW nRow1 = rCxt.maRange.aStart.Row(), nRow2 = rCxt.maRange.aEnd.Row();
991 SCTAB nTab1 = rCxt.maRange.aStart.Tab(), nTab2 = rCxt.maRange.aEnd.Tab();
993 xColNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
994 xRowNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
995 pDBCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
996 if (pRangeName)
997 pRangeName->UpdateReference(rCxt, -1);
998 if ( pDPCollection )
999 pDPCollection->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
1000 UpdateChartRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
1001 UpdateRefAreaLinks( eUpdateRefMode, aRange, nDx, nDy, nDz );
1002 if ( pValidationList )
1003 pValidationList->UpdateReference(rCxt);
1004 if ( pDetOpList )
1005 pDetOpList->UpdateReference( this, eUpdateRefMode, aRange, nDx, nDy, nDz );
1006 if ( pUnoBroadcaster )
1007 pUnoBroadcaster->Broadcast( ScUpdateRefHint(
1008 eUpdateRefMode, aRange, nDx, nDy, nDz ) );
1010 nFirstTab = 0;
1011 nLastTab = maTabs.size()-1;
1014 for (size_t i = nFirstTab, n = maTabs.size() ; i <= nLastTab && i < n; ++i)
1016 if (!maTabs[i])
1017 continue;
1019 maTabs[i]->UpdateReference(rCxt, pUndoDoc, bIncludeDraw, bUpdateNoteCaptionPos);
1022 if ( bIsEmbedded )
1024 SCCOL theCol1;
1025 SCROW theRow1;
1026 SCTAB theTab1;
1027 SCCOL theCol2;
1028 SCROW theRow2;
1029 SCTAB theTab2;
1030 theCol1 = aEmbedRange.aStart.Col();
1031 theRow1 = aEmbedRange.aStart.Row();
1032 theTab1 = aEmbedRange.aStart.Tab();
1033 theCol2 = aEmbedRange.aEnd.Col();
1034 theRow2 = aEmbedRange.aEnd.Row();
1035 theTab2 = aEmbedRange.aEnd.Tab();
1037 // TODO: Have ScRefUpdate::Update() use the context object directly.
1038 UpdateRefMode eUpdateRefMode = rCxt.meMode;
1039 SCCOL nDx = rCxt.mnColDelta;
1040 SCROW nDy = rCxt.mnRowDelta;
1041 SCTAB nDz = rCxt.mnTabDelta;
1042 SCCOL nCol1 = rCxt.maRange.aStart.Col(), nCol2 = rCxt.maRange.aEnd.Col();
1043 SCROW nRow1 = rCxt.maRange.aStart.Row(), nRow2 = rCxt.maRange.aEnd.Row();
1044 SCTAB nTab1 = rCxt.maRange.aStart.Tab(), nTab2 = rCxt.maRange.aEnd.Tab();
1046 if ( ScRefUpdate::Update( this, eUpdateRefMode, nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
1047 nDx,nDy,nDz, theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
1049 aEmbedRange = ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
1053 // After moving, no clipboard move ref-updates are possible
1054 if (rCxt.meMode != URM_COPY && IsClipboardSource())
1056 ScDocument* pClipDoc = ScModule::GetClipDoc();
1057 if (pClipDoc)
1058 pClipDoc->GetClipParam().mbCutMode = false;
1062 void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDoc,
1063 const ScMarkData& rMark, ScDocument* pUndoDoc )
1065 OSL_ENSURE(pClipDoc->bIsClip, "UpdateTranspose: No Clip");
1067 ScRange aSource;
1068 ScClipParam& rClipParam = GetClipParam();
1069 if (!rClipParam.maRanges.empty())
1070 aSource = *rClipParam.maRanges.front();
1071 ScAddress aDest = rDestPos;
1073 SCTAB nClipTab = 0;
1074 for (SCTAB nDestTab=0; nDestTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nDestTab]; nDestTab++)
1075 if (rMark.GetTableSelect(nDestTab))
1077 while (!pClipDoc->maTabs[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
1078 aSource.aStart.SetTab( nClipTab );
1079 aSource.aEnd.SetTab( nClipTab );
1080 aDest.SetTab( nDestTab );
1082 // Like UpdateReference
1083 if (pRangeName)
1084 pRangeName->UpdateTranspose( aSource, aDest ); // Before the cells!
1085 for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++)
1086 if (maTabs[i])
1087 maTabs[i]->UpdateTranspose( aSource, aDest, pUndoDoc );
1089 nClipTab = (nClipTab+1) % (MAXTAB+1);
1093 void ScDocument::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
1095 //TODO: pDBCollection
1096 //TODO: pPivotCollection
1097 //TODO: UpdateChartRef
1099 if (pRangeName)
1100 pRangeName->UpdateGrow( rArea, nGrowX, nGrowY );
1102 for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()) && maTabs[i]; i++)
1103 maTabs[i]->UpdateGrow( rArea, nGrowX, nGrowY );
1106 void ScDocument::Fill(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScProgress* pProgress, const ScMarkData& rMark,
1107 sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1108 double nStepValue, double nMaxValue)
1110 PutInOrder( nCol1, nCol2 );
1111 PutInOrder( nRow1, nRow2 );
1112 SCTAB nMax = maTabs.size();
1113 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1114 for (; itr != itrEnd && *itr < nMax; ++itr)
1115 if (maTabs[*itr])
1116 maTabs[*itr]->Fill(nCol1, nRow1, nCol2, nRow2,
1117 nFillCount, eFillDir, eFillCmd, eFillDateCmd,
1118 nStepValue, nMaxValue, pProgress);
1121 OUString ScDocument::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
1123 SCTAB nTab = rSource.aStart.Tab();
1124 if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
1125 return maTabs[nTab]->GetAutoFillPreview( rSource, nEndX, nEndY );
1127 return OUString();
1130 void ScDocument::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1131 sal_uInt16 nFormatNo, const ScMarkData& rMark )
1133 PutInOrder( nStartCol, nEndCol );
1134 PutInOrder( nStartRow, nEndRow );
1135 SCTAB nMax = maTabs.size();
1136 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1137 for (; itr != itrEnd && *itr < nMax; ++itr)
1138 if (maTabs[*itr])
1139 maTabs[*itr]->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo );
1142 void ScDocument::GetAutoFormatData(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1143 ScAutoFormatData& rData)
1145 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
1147 if (maTabs[nTab])
1149 PutInOrder(nStartCol, nEndCol);
1150 PutInOrder(nStartRow, nEndRow);
1151 maTabs[nTab]->GetAutoFormatData(nStartCol, nStartRow, nEndCol, nEndRow, rData);
1156 void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem& rSearchItem,
1157 SCCOL& rCol, SCROW& rRow )
1159 SvxSearchCmd nCommand = rSearchItem.GetCommand();
1160 bool bReplace = ( nCommand == SvxSearchCmd::REPLACE ||
1161 nCommand == SvxSearchCmd::REPLACE_ALL );
1162 if ( rSearchItem.GetBackward() )
1164 if ( rSearchItem.GetRowDirection() )
1166 if ( rSearchItem.GetPattern() )
1168 rCol = MAXCOL;
1169 rRow = MAXROW+1;
1171 else if ( bReplace )
1173 rCol = MAXCOL;
1174 rRow = MAXROW;
1176 else
1178 rCol = MAXCOL+1;
1179 rRow = MAXROW;
1182 else
1184 if ( rSearchItem.GetPattern() )
1186 rCol = MAXCOL+1;
1187 rRow = MAXROW;
1189 else if ( bReplace )
1191 rCol = MAXCOL;
1192 rRow = MAXROW;
1194 else
1196 rCol = MAXCOL;
1197 rRow = MAXROW+1;
1201 else
1203 if ( rSearchItem.GetRowDirection() )
1205 if ( rSearchItem.GetPattern() )
1207 rCol = 0;
1208 rRow = (SCROW) -1;
1210 else if ( bReplace )
1212 rCol = 0;
1213 rRow = 0;
1215 else
1217 rCol = (SCCOL) -1;
1218 rRow = 0;
1221 else
1223 if ( rSearchItem.GetPattern() )
1225 rCol = (SCCOL) -1;
1226 rRow = 0;
1228 else if ( bReplace )
1230 rCol = 0;
1231 rRow = 0;
1233 else
1235 rCol = 0;
1236 rRow = (SCROW) -1;
1242 bool ScDocument::SearchAndReplace(
1243 const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, SCTAB& rTab,
1244 const ScMarkData& rMark, ScRangeList& rMatchedRanges,
1245 OUString& rUndoStr, ScDocument* pUndoDoc)
1247 // FIXME: Manage separated marks per table!
1248 bool bFound = false;
1249 if (rTab >= static_cast<SCTAB>(maTabs.size()))
1250 OSL_FAIL("table out of range");
1251 if (ValidTab(rTab))
1253 SCCOL nCol;
1254 SCROW nRow;
1255 SCTAB nTab;
1256 SvxSearchCmd nCommand = rSearchItem.GetCommand();
1257 if ( nCommand == SvxSearchCmd::FIND_ALL ||
1258 nCommand == SvxSearchCmd::REPLACE_ALL )
1260 SCTAB nMax = maTabs.size();
1261 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1262 for (; itr != itrEnd && *itr < nMax; ++itr)
1263 if (maTabs[*itr])
1265 nCol = 0;
1266 nRow = 0;
1267 bFound |= maTabs[*itr]->SearchAndReplace(
1268 rSearchItem, nCol, nRow, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
1271 // Mark is set completely inside already
1273 else
1275 nCol = rCol;
1276 nRow = rRow;
1277 if (rSearchItem.GetBackward())
1279 for (nTab = rTab; ((SCsTAB)nTab >= 0) && !bFound; nTab--)
1280 if (maTabs[nTab])
1282 if (rMark.GetTableSelect(nTab))
1284 bFound = maTabs[nTab]->SearchAndReplace(
1285 rSearchItem, nCol, nRow, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
1286 if (bFound)
1288 rCol = nCol;
1289 rRow = nRow;
1290 rTab = nTab;
1292 else
1294 ScDocument::GetSearchAndReplaceStart(
1295 rSearchItem, nCol, nRow );
1297 // notify LibreOfficeKit about changed page
1298 if ( GetDrawLayer() && GetDrawLayer()->isTiledRendering() )
1300 OString aPayload = OString::number(nTab);
1301 GetDrawLayer()->libreOfficeKitCallback(LOK_CALLBACK_SET_PART, aPayload.getStr());
1307 else
1309 for (nTab = rTab; (nTab < static_cast<SCTAB>(maTabs.size())) && !bFound; nTab++)
1310 if (maTabs[nTab])
1312 if (rMark.GetTableSelect(nTab))
1314 bFound = maTabs[nTab]->SearchAndReplace(
1315 rSearchItem, nCol, nRow, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
1316 if (bFound)
1318 rCol = nCol;
1319 rRow = nRow;
1320 rTab = nTab;
1322 else
1324 ScDocument::GetSearchAndReplaceStart(
1325 rSearchItem, nCol, nRow );
1327 // notify LibreOfficeKit about changed page
1328 if ( GetDrawLayer() && GetDrawLayer()->isTiledRendering() )
1330 OString aPayload = OString::number(nTab);
1331 GetDrawLayer()->libreOfficeKitCallback(LOK_CALLBACK_SET_PART, aPayload.getStr());
1339 return bFound;
1343 * Adapt Outline
1345 bool ScDocument::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bShow )
1347 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1348 return maTabs[nTab]->UpdateOutlineCol( nStartCol, nEndCol, bShow );
1350 OSL_FAIL("missing tab");
1351 return false;
1354 bool ScDocument::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bShow )
1356 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1357 return maTabs[nTab]->UpdateOutlineRow( nStartRow, nEndRow, bShow );
1359 OSL_FAIL("missing tab");
1360 return false;
1363 void ScDocument::Sort(
1364 SCTAB nTab, const ScSortParam& rSortParam, bool bKeepQuery, bool bUpdateRefs,
1365 ScProgress* pProgress, sc::ReorderParam* pUndo )
1367 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1369 bool bOldEnableIdle = IsIdleEnabled();
1370 EnableIdle(false);
1371 maTabs[nTab]->Sort(rSortParam, bKeepQuery, bUpdateRefs, pProgress, pUndo);
1372 EnableIdle(bOldEnableIdle);
1376 void ScDocument::Reorder( const sc::ReorderParam& rParam, ScProgress* pProgress )
1378 ScTable* pTab = FetchTable(rParam.maSortRange.aStart.Tab());
1379 if (!pTab)
1380 return;
1382 bool bOldEnableIdle = IsIdleEnabled();
1383 EnableIdle(false);
1384 pTab->Reorder(rParam, pProgress);
1385 EnableIdle(bOldEnableIdle);
1388 SCSIZE ScDocument::Query(SCTAB nTab, const ScQueryParam& rQueryParam, bool bKeepSub)
1390 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1391 return maTabs[nTab]->Query((ScQueryParam&)rQueryParam, bKeepSub);
1393 OSL_FAIL("missing tab");
1394 return 0;
1397 void ScDocument::GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rStr)
1399 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1400 maTabs[nTab]->GetUpperCellString( nCol, nRow, rStr );
1401 else
1402 rStr.clear();
1405 bool ScDocument::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, ScQueryParam& rQueryParam)
1407 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1408 return maTabs[nTab]->CreateQueryParam(nCol1, nRow1, nCol2, nRow2, rQueryParam);
1410 OSL_FAIL("missing tab");
1411 return false;
1414 bool ScDocument::HasAutoFilter( SCCOL nCurCol, SCROW nCurRow, SCTAB nCurTab )
1416 const ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab );
1417 bool bHasAutoFilter = (pDBData != NULL);
1419 if ( pDBData )
1421 if ( pDBData->HasHeader() )
1423 SCCOL nCol;
1424 SCROW nRow;
1425 sal_Int16 nFlag;
1427 ScQueryParam aParam;
1428 pDBData->GetQueryParam( aParam );
1429 nRow = aParam.nRow1;
1431 for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ )
1433 nFlag = static_cast<const ScMergeFlagAttr*>(
1434 GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))->
1435 GetValue();
1437 if ( (nFlag & SC_MF_AUTO) == 0 )
1438 bHasAutoFilter = false;
1441 else
1442 bHasAutoFilter = false;
1445 return bHasAutoFilter;
1448 bool ScDocument::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1449 SCTAB nTab )
1451 return ValidTab(nTab) && maTabs[nTab] && maTabs[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1454 bool ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1455 SCTAB nTab )
1457 return ValidTab(nTab) && maTabs[nTab] && maTabs[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1461 * Entries for AutoFilter listbox
1463 bool ScDocument::GetFilterEntries(
1464 SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, std::vector<ScTypedStrData>& rStrings, bool& rHasDates)
1466 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && pDBCollection )
1468 ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, false); //!??
1469 if (pDBData)
1471 pDBData->ExtendDataArea(this);
1472 SCTAB nAreaTab;
1473 SCCOL nStartCol;
1474 SCROW nStartRow;
1475 SCCOL nEndCol;
1476 SCROW nEndRow;
1477 pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1479 if (pDBData->HasHeader())
1480 ++nStartRow;
1482 ScQueryParam aParam;
1483 pDBData->GetQueryParam( aParam );
1485 // Return all filter entries, if a filter condition is connected with a boolean OR
1486 if ( bFilter )
1488 SCSIZE nEntryCount = aParam.GetEntryCount();
1489 for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i )
1491 ScQueryEntry& rEntry = aParam.GetEntry(i);
1492 if ( rEntry.eConnect != SC_AND )
1494 bFilter = false;
1495 break;
1500 if ( bFilter )
1502 maTabs[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates );
1504 else
1506 maTabs[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
1509 sortAndRemoveDuplicates(rStrings, aParam.bCaseSens);
1510 return true;
1514 return false;
1518 * Entries for Filter dialog
1520 bool ScDocument::GetFilterEntriesArea(
1521 SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bCaseSens,
1522 std::vector<ScTypedStrData>& rStrings, bool& rHasDates)
1524 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1526 maTabs[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
1527 sortAndRemoveDuplicates(rStrings, bCaseSens);
1528 return true;
1531 return false;
1535 * Entries for selection list listbox (no numbers/formulas)
1537 bool ScDocument::GetDataEntries(
1538 SCCOL nCol, SCROW nRow, SCTAB nTab, bool bCaseSens,
1539 std::vector<ScTypedStrData>& rStrings, bool bLimit )
1541 if( !bLimit )
1543 /* Try to generate the list from list validation. This part is skipped,
1544 if bLimit==true, because in that case this function is called to get
1545 cell values for auto completion on input. */
1546 sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
1547 if( nValidation )
1549 const ScValidationData* pData = GetValidationEntry( nValidation );
1550 if( pData && pData->FillSelectionList( rStrings, ScAddress( nCol, nRow, nTab ) ) )
1552 if (pData->GetListType() == css::sheet::TableValidationVisibility::SORTEDASCENDING)
1553 sortAndRemoveDuplicates(rStrings, bCaseSens);
1555 return true;
1560 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()))
1561 return false;
1563 if (!maTabs[nTab])
1564 return false;
1566 std::set<ScTypedStrData> aStrings;
1567 bool bRet = maTabs[nTab]->GetDataEntries(nCol, nRow, aStrings, bLimit);
1568 rStrings.insert(rStrings.end(), aStrings.begin(), aStrings.end());
1569 sortAndRemoveDuplicates(rStrings, bCaseSens);
1571 return bRet;
1575 * Entries for Formula auto input
1577 bool ScDocument::GetFormulaEntries( ScTypedCaseStrSet& rStrings )
1580 // Range name
1581 if ( pRangeName )
1583 ScRangeName::const_iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
1584 for (; itr != itrEnd; ++itr)
1585 rStrings.insert(ScTypedStrData(itr->second->GetName(), 0.0, ScTypedStrData::Name));
1588 // Database collection
1589 if ( pDBCollection )
1591 const ScDBCollection::NamedDBs& rDBs = pDBCollection->getNamedDBs();
1592 ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
1593 for (; itr != itrEnd; ++itr)
1594 rStrings.insert(ScTypedStrData(itr->GetName(), 0.0, ScTypedStrData::DbName));
1597 // Content of name ranges
1598 ScRangePairList* pLists[2];
1599 pLists[0] = GetColNameRanges();
1600 pLists[1] = GetRowNameRanges();
1601 for (sal_uInt16 nListNo=0; nListNo<2; nListNo++)
1603 ScRangePairList* pList = pLists[ nListNo ];
1604 if (!pList)
1605 continue;
1607 for ( size_t i = 0, nPairs = pList->size(); i < nPairs; ++i )
1609 ScRangePair* pPair = (*pList)[i];
1610 ScRange aRange = pPair->GetRange(0);
1611 ScCellIterator aIter( this, aRange );
1612 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
1614 if (!aIter.hasString())
1615 continue;
1617 OUString aStr = aIter.getString();
1618 rStrings.insert(ScTypedStrData(aStr, 0.0, ScTypedStrData::Header));
1623 return true;
1626 void ScDocument::GetEmbedded( ScRange& rRange ) const
1628 rRange = aEmbedRange;
1631 Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm
1633 Rectangle aRect;
1634 ScTable* pTable = NULL;
1635 if ( aEmbedRange.aStart.Tab() < static_cast<SCTAB>(maTabs.size()) )
1636 pTable = maTabs[aEmbedRange.aStart.Tab()];
1637 else
1638 OSL_FAIL("table out of range");
1639 if (!pTable)
1641 OSL_FAIL("GetEmbeddedRect without a table");
1643 else
1645 SCCOL i;
1647 for (i=0; i<aEmbedRange.aStart.Col(); i++)
1648 aRect.Left() += pTable->GetColWidth(i);
1649 aRect.Top() += pTable->GetRowHeight( 0, aEmbedRange.aStart.Row() - 1);
1650 aRect.Right() = aRect.Left();
1651 for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++)
1652 aRect.Right() += pTable->GetColWidth(i);
1653 aRect.Bottom() = aRect.Top();
1654 aRect.Bottom() += pTable->GetRowHeight( aEmbedRange.aStart.Row(), aEmbedRange.aEnd.Row());
1656 aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS );
1657 aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS );
1658 aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS );
1659 aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS );
1661 return aRect;
1664 void ScDocument::SetEmbedded( const ScRange& rRange )
1666 bIsEmbedded = true;
1667 aEmbedRange = rRange;
1670 void ScDocument::ResetEmbedded()
1672 bIsEmbedded = false;
1673 aEmbedRange = ScRange();
1676 /** Similar to ScViewData::AddPixelsWhile(), but add height twips and only
1677 while result is less than nStopTwips.
1678 @return true if advanced at least one row.
1680 static bool lcl_AddTwipsWhile( long & rTwips, long nStopTwips, SCROW & rPosY, SCROW nEndRow, const ScTable * pTable, bool bHiddenAsZero = true )
1682 SCROW nRow = rPosY;
1683 bool bAdded = false;
1684 bool bStop = false;
1685 while (rTwips < nStopTwips && nRow <= nEndRow && !bStop)
1687 SCROW nHeightEndRow;
1688 sal_uInt16 nHeight = pTable->GetRowHeight( nRow, NULL, &nHeightEndRow, bHiddenAsZero );
1689 if (nHeightEndRow > nEndRow)
1690 nHeightEndRow = nEndRow;
1691 if (!nHeight)
1692 nRow = nHeightEndRow + 1;
1693 else
1695 SCROW nRows = nHeightEndRow - nRow + 1;
1696 sal_Int64 nAdd = static_cast<sal_Int64>(nHeight) * nRows;
1697 if (nAdd + rTwips >= nStopTwips)
1699 sal_Int64 nDiff = nAdd + rTwips - nStopTwips;
1700 nRows -= static_cast<SCROW>(nDiff / nHeight);
1701 nAdd = static_cast<sal_Int64>(nHeight) * nRows;
1702 // We're looking for a value that satisfies loop condition.
1703 if (nAdd + rTwips >= nStopTwips)
1705 --nRows;
1706 nAdd -= nHeight;
1708 bStop = true;
1710 rTwips += static_cast<long>(nAdd);
1711 nRow += nRows;
1714 if (nRow > rPosY)
1716 --nRow;
1717 bAdded = true;
1719 rPosY = nRow;
1720 return bAdded;
1723 ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect, bool bHiddenAsZero ) const
1725 ScTable* pTable = NULL;
1726 if (nTab < static_cast<SCTAB>(maTabs.size()))
1727 pTable = maTabs[nTab];
1728 else
1729 OSL_FAIL("table out of range");
1730 if (!pTable)
1732 OSL_FAIL("GetRange without a table");
1733 return ScRange();
1736 Rectangle aPosRect = rMMRect;
1737 if ( IsNegativePage( nTab ) )
1738 ScDrawLayer::MirrorRectRTL( aPosRect ); // Always with positive (LTR) values
1740 long nSize;
1741 long nTwips;
1742 long nAdd;
1743 bool bEnd;
1745 nSize = 0;
1746 nTwips = (long) (aPosRect.Left() / HMM_PER_TWIPS);
1748 SCCOL nX1 = 0;
1749 bEnd = false;
1750 while (!bEnd)
1752 nAdd = (long) pTable->GetColWidth(nX1, bHiddenAsZero);
1753 if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL)
1755 nSize += nAdd;
1756 ++nX1;
1758 else
1759 bEnd = true;
1762 nTwips = (long) (aPosRect.Right() / HMM_PER_TWIPS);
1764 SCCOL nX2 = nX1;
1765 bEnd = false;
1766 while (!bEnd)
1768 nAdd = (long) pTable->GetColWidth(nX2, bHiddenAsZero);
1769 if (nSize+nAdd < nTwips && nX2<MAXCOL)
1771 nSize += nAdd;
1772 ++nX2;
1774 else
1775 bEnd = true;
1778 nSize = 0;
1779 nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS);
1781 SCROW nY1 = 0;
1782 // Was if(nSize+nAdd<=nTwips+1) inside loop => if(nSize+nAdd<nTwips+2)
1783 if (lcl_AddTwipsWhile( nSize, nTwips+2, nY1, MAXROW, pTable, bHiddenAsZero) && nY1 < MAXROW)
1784 ++nY1; // original loop ended on last matched +1 unless that was MAXROW
1786 nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS);
1788 SCROW nY2 = nY1;
1789 // Was if(nSize+nAdd<nTwips) inside loop => if(nSize+nAdd<nTwips)
1790 if (lcl_AddTwipsWhile( nSize, nTwips, nY2, MAXROW, pTable, bHiddenAsZero) && nY2 < MAXROW)
1791 ++nY2; // original loop ended on last matched +1 unless that was MAXROW
1793 return ScRange( nX1,nY1,nTab, nX2,nY2,nTab );
1796 void ScDocument::SetEmbedded( SCTAB nTab, const Rectangle& rRect ) // From VisArea (1/100 mm)
1798 bIsEmbedded = true;
1799 aEmbedRange = GetRange( nTab, rRect );
1802 ScDocProtection* ScDocument::GetDocProtection() const
1804 return pDocProtection.get();
1807 void ScDocument::SetDocProtection(const ScDocProtection* pProtect)
1809 if (pProtect)
1810 pDocProtection.reset(new ScDocProtection(*pProtect));
1811 else
1812 pDocProtection.reset();
1815 bool ScDocument::IsDocProtected() const
1817 return pDocProtection.get() && pDocProtection->isProtected();
1820 bool ScDocument::IsDocEditable() const
1822 // Import into read-only document is possible
1823 return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
1826 bool ScDocument::IsTabProtected( SCTAB nTab ) const
1828 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
1829 return maTabs[nTab]->IsProtected();
1831 OSL_FAIL("Wrong table number");
1832 return false;
1835 ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const
1837 if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
1838 return maTabs[nTab]->GetProtection();
1840 return NULL;
1843 void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect)
1845 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()))
1846 return;
1848 maTabs[nTab]->SetProtection(pProtect);
1851 void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest)
1853 if (!ValidTab(nTabSrc) || nTabSrc >= static_cast<SCTAB>(maTabs.size()) || nTabDest >= static_cast<SCTAB>(maTabs.size()) || !ValidTab(nTabDest))
1854 return;
1856 maTabs[nTabDest]->SetProtection( maTabs[nTabSrc]->GetProtection() );
1859 const ScDocOptions& ScDocument::GetDocOptions() const
1861 assert(pDocOptions && "No DocOptions! :-(");
1862 return *pDocOptions;
1865 void ScDocument::SetDocOptions( const ScDocOptions& rOpt )
1867 assert(pDocOptions && "No DocOptions! :-(");
1869 *pDocOptions = rOpt;
1870 xPoolHelper->SetFormTableOpt(rOpt);
1873 const ScViewOptions& ScDocument::GetViewOptions() const
1875 assert(pViewOptions && "No ViewOptions! :-(");
1876 return *pViewOptions;
1879 void ScDocument::SetViewOptions( const ScViewOptions& rOpt )
1881 assert(pViewOptions && "No ViewOptions! :-(");
1882 *pViewOptions = rOpt;
1885 void ScDocument::GetLanguage( LanguageType& rLatin, LanguageType& rCjk, LanguageType& rCtl ) const
1887 rLatin = eLanguage;
1888 rCjk = eCjkLanguage;
1889 rCtl = eCtlLanguage;
1892 void ScDocument::SetLanguage( LanguageType eLatin, LanguageType eCjk, LanguageType eCtl )
1894 eLanguage = eLatin;
1895 eCjkLanguage = eCjk;
1896 eCtlLanguage = eCtl;
1897 if ( xPoolHelper.is() )
1899 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
1900 pPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) );
1901 pPool->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage, ATTR_CJK_FONT_LANGUAGE ) );
1902 pPool->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage, ATTR_CTL_FONT_LANGUAGE ) );
1905 UpdateDrawLanguages(); // Set edit engine defaults in drawing layer pool
1908 Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, bool bHiddenAsZero ) const
1910 if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
1912 OSL_FAIL("GetMMRect: wrong table");
1913 return Rectangle(0,0,0,0);
1916 SCCOL i;
1917 Rectangle aRect;
1919 for (i=0; i<nStartCol; i++)
1920 aRect.Left() += GetColWidth(i,nTab, bHiddenAsZero );
1921 aRect.Top() += GetRowHeight( 0, nStartRow-1, nTab, bHiddenAsZero );
1923 aRect.Right() = aRect.Left();
1924 aRect.Bottom() = aRect.Top();
1926 for (i=nStartCol; i<=nEndCol; i++)
1927 aRect.Right() += GetColWidth(i,nTab, bHiddenAsZero);
1928 aRect.Bottom() += GetRowHeight( nStartRow, nEndRow, nTab, bHiddenAsZero );
1930 aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS);
1931 aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS);
1932 aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS);
1933 aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS);
1935 if ( IsNegativePage( nTab ) )
1936 ScDrawLayer::MirrorRectRTL( aRect );
1938 return aRect;
1941 void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions )
1943 delete pExtDocOptions;
1944 pExtDocOptions = pNewOptions;
1947 void ScDocument::DoMergeContents( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1948 SCCOL nEndCol, SCROW nEndRow )
1950 OUString aEmpty;
1951 OUStringBuffer aTotal;
1952 OUString aCellStr;
1953 SCCOL nCol;
1954 SCROW nRow;
1955 for (nRow=nStartRow; nRow<=nEndRow; nRow++)
1956 for (nCol=nStartCol; nCol<=nEndCol; nCol++)
1958 aCellStr = GetString(nCol, nRow, nTab);
1959 if (!aCellStr.isEmpty())
1961 if (!aTotal.isEmpty())
1962 aTotal.append(' ');
1963 aTotal.append(aCellStr);
1965 if (nCol != nStartCol || nRow != nStartRow)
1966 SetString(nCol,nRow,nTab,aEmpty);
1969 SetString(nStartCol,nStartRow,nTab,aTotal.makeStringAndClear());
1972 void ScDocument::DoMerge( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1973 SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions )
1975 ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 );
1976 ApplyAttr( nStartCol, nStartRow, nTab, aAttr );
1978 if ( nEndCol > nStartCol )
1979 ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR );
1980 if ( nEndRow > nStartRow )
1981 ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER );
1982 if ( nEndCol > nStartCol && nEndRow > nStartRow )
1983 ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1985 // Remove all covered notes (removed captions are collected by drawing undo if active)
1986 InsertDeleteFlags nDelFlag = IDF_NOTE | (bDeleteCaptions ? IDF_NONE : IDF_NOCAPTIONS);
1987 if( nStartCol < nEndCol )
1988 DeleteAreaTab( nStartCol + 1, nStartRow, nEndCol, nStartRow, nTab, nDelFlag );
1989 if( nStartRow < nEndRow )
1990 DeleteAreaTab( nStartCol, nStartRow + 1, nEndCol, nEndRow, nTab, nDelFlag );
1993 void ScDocument::RemoveMerge( SCCOL nCol, SCROW nRow, SCTAB nTab )
1995 const ScMergeAttr* pAttr = static_cast<const ScMergeAttr*>(
1996 GetAttr( nCol, nRow, nTab, ATTR_MERGE ));
1998 if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 )
1999 return;
2001 SCCOL nEndCol = nCol + pAttr->GetColMerge() - 1;
2002 SCROW nEndRow = nRow + pAttr->GetRowMerge() - 1;
2004 RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
2006 const ScMergeAttr* pDefAttr = static_cast<const ScMergeAttr*>(
2007 &xPoolHelper->GetDocPool()->GetDefaultItem( ATTR_MERGE ));
2008 ApplyAttr( nCol, nRow, nTab, *pDefAttr );
2011 void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab,
2012 SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow ) const
2014 if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
2015 maTabs[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow );
2018 SCSIZE ScDocument::GetPatternCount( SCTAB nTab, SCCOL nCol ) const
2020 if( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
2021 return maTabs[nTab]->GetPatternCount( nCol );
2022 else
2023 return 0;
2026 SCSIZE ScDocument::GetPatternCount( SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const
2028 if( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
2029 return maTabs[nTab]->GetPatternCount( nCol, nRow1, nRow2 );
2030 else
2031 return 0;
2034 bool ScDocument::ReservePatternCount( SCTAB nTab, SCCOL nCol, SCSIZE nReserve )
2036 if( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
2037 return maTabs[nTab]->ReservePatternCount( nCol, nReserve );
2038 else
2039 return false;
2042 void ScDocument::GetSortParam( ScSortParam& rParam, SCTAB nTab )
2044 rParam = mSheetSortParams[ nTab ];
2047 void ScDocument::SetSortParam( ScSortParam& rParam, SCTAB nTab )
2049 mSheetSortParams[ nTab ] = rParam;
2052 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */