Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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"
74 :
75 : #include "globalnames.hxx"
76 : #include <boost/scoped_ptr.hpp>
77 :
78 : using namespace com::sun::star;
79 :
80 : namespace {
81 :
82 4 : void sortAndRemoveDuplicates(std::vector<ScTypedStrData>& rStrings, bool bCaseSens)
83 : {
84 4 : if (bCaseSens)
85 : {
86 4 : std::sort(rStrings.begin(), rStrings.end(), ScTypedStrData::LessCaseSensitive());
87 : std::vector<ScTypedStrData>::iterator it =
88 4 : std::unique(rStrings.begin(), rStrings.end(), ScTypedStrData::EqualCaseSensitive());
89 4 : rStrings.erase(it, rStrings.end());
90 : }
91 : else
92 : {
93 0 : std::sort(rStrings.begin(), rStrings.end(), ScTypedStrData::LessCaseInsensitive());
94 : std::vector<ScTypedStrData>::iterator it =
95 0 : std::unique(rStrings.begin(), rStrings.end(), ScTypedStrData::EqualCaseInsensitive());
96 0 : rStrings.erase(it, rStrings.end());
97 : }
98 4 : }
99 :
100 : }
101 :
102 122 : void ScDocument::GetAllTabRangeNames(ScRangeName::TabNameCopyMap& rNames) const
103 : {
104 122 : ScRangeName::TabNameCopyMap aNames;
105 368 : for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); ++i)
106 : {
107 246 : if (!maTabs[i])
108 : // no more tables to iterate through.
109 0 : break;
110 :
111 246 : const ScRangeName* p = maTabs[i]->mpRangeName;
112 246 : if (!p || p->empty())
113 : // ignore empty ones.
114 234 : continue;
115 :
116 12 : aNames.insert(ScRangeName::TabNameCopyMap::value_type(i, p));
117 : }
118 122 : rNames.swap(aNames);
119 122 : }
120 :
121 2 : void ScDocument::SetAllRangeNames( const boost::ptr_map<OUString, ScRangeName>& rRangeMap)
122 : {
123 2 : OUString aGlobalStr(STR_GLOBAL_RANGE_NAME);
124 2 : boost::ptr_map<OUString,ScRangeName>::const_iterator itr = rRangeMap.begin(), itrEnd = rRangeMap.end();
125 4 : for (; itr!=itrEnd; ++itr)
126 : {
127 2 : if (itr->first == aGlobalStr)
128 : {
129 2 : delete pRangeName;
130 2 : const ScRangeName* pName = itr->second;
131 2 : if (pName->empty())
132 0 : pRangeName = NULL;
133 : else
134 2 : pRangeName = new ScRangeName( *pName );
135 : }
136 : else
137 : {
138 0 : const ScRangeName* pName = itr->second;
139 : SCTAB nTab;
140 0 : bool bFound = GetTable(itr->first, nTab);
141 : assert(bFound); (void)bFound; // fouled up?
142 0 : if (pName->empty())
143 0 : SetRangeName( nTab, NULL );
144 : else
145 0 : SetRangeName( nTab, new ScRangeName( *pName ) );
146 : }
147 2 : }
148 2 : }
149 :
150 2 : void ScDocument::GetTabRangeNameMap(std::map<OUString, ScRangeName*>& aRangeNameMap)
151 : {
152 4 : for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); ++i)
153 : {
154 2 : if (!maTabs[i])
155 0 : continue;
156 2 : ScRangeName* p = maTabs[i]->GetRangeName();
157 2 : if (!p )
158 : {
159 0 : p = new ScRangeName();
160 0 : SetRangeName(i, p);
161 : }
162 2 : OUString aTableName;
163 2 : maTabs[i]->GetName(aTableName);
164 2 : aRangeNameMap.insert(std::pair<OUString, ScRangeName*>(aTableName,p));
165 2 : }
166 2 : }
167 :
168 2 : void ScDocument::GetRangeNameMap(std::map<OUString, ScRangeName*>& aRangeNameMap)
169 : {
170 2 : GetTabRangeNameMap(aRangeNameMap);
171 2 : if (!pRangeName)
172 : {
173 0 : pRangeName = new ScRangeName();
174 : }
175 2 : OUString aGlobal(STR_GLOBAL_RANGE_NAME);
176 2 : aRangeNameMap.insert(std::pair<OUString, ScRangeName*>(aGlobal, pRangeName));
177 2 : }
178 :
179 3786 : ScRangeName* ScDocument::GetRangeName(SCTAB nTab) const
180 : {
181 3786 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
182 2 : return NULL;
183 :
184 3784 : return maTabs[nTab]->GetRangeName();
185 : }
186 :
187 8198 : ScRangeName* ScDocument::GetRangeName() const
188 : {
189 8198 : if (!pRangeName)
190 766 : pRangeName = new ScRangeName;
191 8198 : return pRangeName;
192 : }
193 :
194 2 : void ScDocument::SetRangeName(SCTAB nTab, ScRangeName* pNew)
195 : {
196 2 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
197 0 : return;
198 :
199 2 : return maTabs[nTab]->SetRangeName(pNew);
200 : }
201 :
202 80 : void ScDocument::SetRangeName( ScRangeName* pNewRangeName )
203 : {
204 80 : if (pRangeName == pNewRangeName)
205 80 : return;
206 :
207 80 : delete pRangeName;
208 80 : pRangeName = pNewRangeName;
209 : }
210 :
211 12 : bool ScDocument::InsertNewRangeName( const OUString& rName, const ScAddress& rPos, const OUString& rExpr )
212 : {
213 12 : ScRangeName* pGlobalNames = GetRangeName();
214 12 : if (!pGlobalNames)
215 0 : return false;
216 :
217 12 : ScRangeData* pName = new ScRangeData(this, rName, rExpr, rPos, RT_NAME, GetGrammar());
218 12 : return pGlobalNames->insert(pName);
219 : }
220 :
221 1696 : const ScRangeData* ScDocument::GetRangeAtBlock( const ScRange& rBlock, OUString* pName ) const
222 : {
223 1696 : const ScRangeData* pData = NULL;
224 1696 : if ( pRangeName )
225 : {
226 668 : pData = pRangeName->findByRange( rBlock );
227 668 : if (pData && pName)
228 12 : *pName = pData->GetName();
229 : }
230 1696 : return pData;
231 : }
232 :
233 38 : void ScDocument::SetDBCollection( ScDBCollection* pNewDBCollection, bool bRemoveAutoFilter )
234 : {
235 38 : if (pDBCollection && bRemoveAutoFilter)
236 : {
237 : // remove auto filter attribute if new db data don't contain auto filter flag
238 : // start position is also compared, so bRemoveAutoFilter must not be set from ref-undo!
239 :
240 4 : ScDBCollection::NamedDBs& rNamedDBs = pDBCollection->getNamedDBs();
241 4 : ScDBCollection::NamedDBs::const_iterator itr = rNamedDBs.begin(), itrEnd = rNamedDBs.end();
242 8 : for (; itr != itrEnd; ++itr)
243 : {
244 4 : const ScDBData& rOldData = *itr;
245 4 : if (!rOldData.HasAutoFilter())
246 4 : continue;
247 :
248 0 : ScRange aOldRange;
249 0 : rOldData.GetArea(aOldRange);
250 :
251 0 : bool bFound = false;
252 0 : if (pNewDBCollection)
253 : {
254 0 : ScDBData* pNewData = pNewDBCollection->getNamedDBs().findByUpperName(rOldData.GetUpperName());
255 0 : if (pNewData)
256 : {
257 0 : if (pNewData->HasAutoFilter())
258 : {
259 0 : ScRange aNewRange;
260 0 : pNewData->GetArea(aNewRange);
261 0 : if (aOldRange.aStart == aNewRange.aStart)
262 0 : bFound = true;
263 : }
264 : }
265 : }
266 :
267 0 : if (!bFound)
268 : {
269 0 : aOldRange.aEnd.SetRow(aOldRange.aStart.Row());
270 0 : RemoveFlagsTab( aOldRange.aStart.Col(), aOldRange.aStart.Row(),
271 0 : aOldRange.aEnd.Col(), aOldRange.aEnd.Row(),
272 0 : aOldRange.aStart.Tab(), SC_MF_AUTO );
273 0 : RepaintRange( aOldRange );
274 : }
275 : }
276 : }
277 :
278 38 : delete pDBCollection;
279 :
280 38 : pDBCollection = pNewDBCollection;
281 38 : }
282 :
283 0 : const ScDBData* ScDocument::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly) const
284 : {
285 0 : if (pDBCollection)
286 0 : return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly);
287 : else
288 0 : return NULL;
289 : }
290 :
291 13 : ScDBData* ScDocument::GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, bool bStartOnly)
292 : {
293 13 : if (pDBCollection)
294 13 : return pDBCollection->GetDBAtCursor(nCol, nRow, nTab, bStartOnly);
295 : else
296 0 : return NULL;
297 : }
298 :
299 0 : const ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
300 : {
301 0 : if (pDBCollection)
302 0 : return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2);
303 : else
304 0 : return NULL;
305 : }
306 :
307 126 : ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
308 : {
309 126 : if (pDBCollection)
310 126 : return pDBCollection->GetDBAtArea(nTab, nCol1, nRow1, nCol2, nRow2);
311 : else
312 0 : return NULL;
313 : }
314 :
315 1374 : bool ScDocument::HasPivotTable() const
316 : {
317 1374 : return pDPCollection && pDPCollection->GetCount();
318 : }
319 :
320 2705 : ScDPCollection* ScDocument::GetDPCollection()
321 : {
322 2705 : if (!pDPCollection)
323 466 : pDPCollection = new ScDPCollection(this);
324 2705 : return pDPCollection;
325 : }
326 :
327 12 : const ScDPCollection* ScDocument::GetDPCollection() const
328 : {
329 12 : return pDPCollection;
330 : }
331 :
332 902 : ScDPObject* ScDocument::GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
333 : {
334 902 : if (!pDPCollection)
335 642 : return NULL;
336 :
337 260 : sal_uInt16 nCount = pDPCollection->GetCount();
338 260 : ScAddress aPos( nCol, nRow, nTab );
339 458 : for (sal_uInt16 i=0; i<nCount; i++)
340 212 : if ( (*pDPCollection)[i]->GetOutRange().In( aPos ) )
341 14 : return (*pDPCollection)[i];
342 :
343 246 : return NULL;
344 : }
345 :
346 62 : ScDPObject* ScDocument::GetDPAtBlock( const ScRange & rBlock ) const
347 : {
348 62 : if (!pDPCollection)
349 0 : return NULL;
350 :
351 : /* Walk the collection in reverse order to get something of an
352 : * approximation of MS Excels 'most recent' effect. */
353 62 : sal_uInt16 i = pDPCollection->GetCount();
354 124 : while ( i-- > 0 )
355 62 : if ( (*pDPCollection)[i]->GetOutRange().In( rBlock ) )
356 62 : return (*pDPCollection)[i];
357 :
358 0 : return NULL;
359 : }
360 :
361 48 : void ScDocument::StopTemporaryChartLock()
362 : {
363 48 : if( apTemporaryChartLock.get() )
364 48 : apTemporaryChartLock->StopLocking();
365 48 : }
366 :
367 0 : void ScDocument::SetChartListenerCollection(
368 : ScChartListenerCollection* pNewChartListenerCollection,
369 : bool bSetChartRangeLists )
370 : {
371 0 : ScChartListenerCollection* pOld = pChartListenerCollection;
372 0 : pChartListenerCollection = pNewChartListenerCollection;
373 0 : if ( pChartListenerCollection )
374 : {
375 0 : if ( pOld )
376 0 : pChartListenerCollection->SetDiffDirty( *pOld, bSetChartRangeLists );
377 0 : pChartListenerCollection->StartAllListeners();
378 : }
379 0 : delete pOld;
380 0 : }
381 :
382 2 : void ScDocument::SetScenario( SCTAB nTab, bool bFlag )
383 : {
384 2 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
385 2 : maTabs[nTab]->SetScenario(bFlag);
386 2 : }
387 :
388 8261 : bool ScDocument::IsScenario( SCTAB nTab ) const
389 : {
390 8261 : return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] &&maTabs[nTab]->IsScenario();
391 : }
392 :
393 2 : void ScDocument::SetScenarioData( SCTAB nTab, const OUString& rComment,
394 : const Color& rColor, sal_uInt16 nFlags )
395 : {
396 2 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario())
397 : {
398 2 : maTabs[nTab]->SetScenarioComment( rComment );
399 2 : maTabs[nTab]->SetScenarioColor( rColor );
400 2 : maTabs[nTab]->SetScenarioFlags( nFlags );
401 : }
402 2 : }
403 :
404 6904 : Color ScDocument::GetTabBgColor( SCTAB nTab ) const
405 : {
406 6904 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
407 6904 : return maTabs[nTab]->GetTabBgColor();
408 0 : return Color(COL_AUTO);
409 : }
410 :
411 98 : void ScDocument::SetTabBgColor( SCTAB nTab, const Color& rColor )
412 : {
413 98 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
414 98 : maTabs[nTab]->SetTabBgColor(rColor);
415 98 : }
416 :
417 1318 : bool ScDocument::IsDefaultTabBgColor( SCTAB nTab ) const
418 : {
419 1318 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
420 1318 : return maTabs[nTab]->GetTabBgColor() == COL_AUTO;
421 0 : return true;
422 : }
423 :
424 0 : void ScDocument::GetScenarioData( SCTAB nTab, OUString& rComment,
425 : Color& rColor, sal_uInt16& rFlags ) const
426 : {
427 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario())
428 : {
429 0 : maTabs[nTab]->GetScenarioComment( rComment );
430 0 : rColor = maTabs[nTab]->GetScenarioColor();
431 0 : rFlags = maTabs[nTab]->GetScenarioFlags();
432 : }
433 0 : }
434 :
435 0 : void ScDocument::GetScenarioFlags( SCTAB nTab, sal_uInt16& rFlags ) const
436 : {
437 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario())
438 0 : rFlags = maTabs[nTab]->GetScenarioFlags();
439 0 : }
440 :
441 2288 : bool ScDocument::IsLinked( SCTAB nTab ) const
442 : {
443 2288 : return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsLinked();
444 : // euqivalent to
445 : //if (ValidTab(nTab) && pTab[nTab])
446 : // return pTab[nTab]->IsLinked();
447 : //return false;
448 : }
449 :
450 103944 : formula::FormulaGrammar::AddressConvention ScDocument::GetAddressConvention() const
451 : {
452 103944 : return formula::FormulaGrammar::extractRefConvention(eGrammar);
453 : }
454 :
455 1026 : void ScDocument::SetGrammar( formula::FormulaGrammar::Grammar eGram )
456 : {
457 1026 : eGrammar = eGram;
458 1026 : }
459 :
460 184 : sal_uInt8 ScDocument::GetLinkMode( SCTAB nTab ) const
461 : {
462 184 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
463 184 : return maTabs[nTab]->GetLinkMode();
464 0 : return SC_LINK_NONE;
465 : }
466 :
467 40 : const OUString ScDocument::GetLinkDoc( SCTAB nTab ) const
468 : {
469 40 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
470 40 : return maTabs[nTab]->GetLinkDoc();
471 0 : return OUString();
472 : }
473 :
474 4 : const OUString ScDocument::GetLinkFlt( SCTAB nTab ) const
475 : {
476 4 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
477 4 : return maTabs[nTab]->GetLinkFlt();
478 0 : return OUString();
479 : }
480 :
481 4 : const OUString ScDocument::GetLinkOpt( SCTAB nTab ) const
482 : {
483 4 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
484 4 : return maTabs[nTab]->GetLinkOpt();
485 0 : return OUString();
486 : }
487 :
488 4 : const OUString ScDocument::GetLinkTab( SCTAB nTab ) const
489 : {
490 4 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
491 4 : return maTabs[nTab]->GetLinkTab();
492 0 : return OUString();
493 : }
494 :
495 4 : sal_uLong ScDocument::GetLinkRefreshDelay( SCTAB nTab ) const
496 : {
497 4 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
498 4 : return maTabs[nTab]->GetLinkRefreshDelay();
499 0 : return 0;
500 : }
501 :
502 8 : void ScDocument::SetLink( SCTAB nTab, sal_uInt8 nMode, const OUString& rDoc,
503 : const OUString& rFilter, const OUString& rOptions,
504 : const OUString& rTabName, sal_uLong nRefreshDelay )
505 : {
506 8 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
507 8 : maTabs[nTab]->SetLink( nMode, rDoc, rFilter, rOptions, rTabName, nRefreshDelay );
508 8 : }
509 :
510 0 : bool ScDocument::HasLink( const OUString& rDoc,
511 : const OUString& rFilter, const OUString& rOptions ) const
512 : {
513 0 : SCTAB nCount = static_cast<SCTAB>(maTabs.size());
514 0 : for (SCTAB i=0; i<nCount; i++)
515 0 : if (maTabs[i]->IsLinked()
516 0 : && maTabs[i]->GetLinkDoc() == rDoc
517 0 : && maTabs[i]->GetLinkFlt() == rFilter
518 0 : && maTabs[i]->GetLinkOpt() == rOptions)
519 0 : return true;
520 :
521 0 : return false;
522 : }
523 :
524 0 : bool ScDocument::LinkExternalTab( SCTAB& rTab, const OUString& aDocTab,
525 : const OUString& aFileName, const OUString& aTabName )
526 : {
527 0 : if ( IsClipboard() )
528 : {
529 : OSL_FAIL( "LinkExternalTab in Clipboard" );
530 0 : return false;
531 : }
532 0 : rTab = 0;
533 0 : OUString aFilterName; // Is filled by the Loader
534 0 : OUString aOptions; // Filter options
535 0 : sal_uInt32 nLinkCnt = pExtDocOptions ? pExtDocOptions->GetDocSettings().mnLinkCnt : 0;
536 0 : ScDocumentLoader aLoader( aFileName, aFilterName, aOptions, nLinkCnt + 1 );
537 0 : if ( aLoader.IsError() )
538 0 : return false;
539 0 : ScDocument* pSrcDoc = aLoader.GetDocument();
540 :
541 : // Copy table
542 : SCTAB nSrcTab;
543 0 : if ( pSrcDoc->GetTable( aTabName, nSrcTab ) )
544 : {
545 0 : if ( !InsertTab( SC_TAB_APPEND, aDocTab, true ) )
546 : {
547 : OSL_FAIL("can't insert external document table");
548 0 : return false;
549 : }
550 0 : rTab = GetTableCount() - 1;
551 : // Don't insert anew, just the results
552 0 : TransferTab( pSrcDoc, nSrcTab, rTab, false, true );
553 : }
554 : else
555 0 : return false;
556 :
557 0 : sal_uLong nRefreshDelay = 0;
558 :
559 0 : bool bWasThere = HasLink( aFileName, aFilterName, aOptions );
560 0 : SetLink( rTab, SC_LINK_VALUE, aFileName, aFilterName, aOptions, aTabName, nRefreshDelay );
561 0 : if ( !bWasThere ) // Add link only once per source document
562 : {
563 0 : ScTableLink* pLink = new ScTableLink( pShell, aFileName, aFilterName, aOptions, nRefreshDelay );
564 0 : pLink->SetInCreate( true );
565 0 : OUString aFilName = aFilterName;
566 : GetLinkManager()->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, OUString(aFileName),
567 0 : &aFilName );
568 0 : pLink->Update();
569 0 : pLink->SetInCreate( false );
570 0 : SfxBindings* pBindings = GetViewBindings();
571 0 : if (pBindings)
572 0 : pBindings->Invalidate( SID_LINKS );
573 : }
574 0 : return true;
575 : }
576 :
577 8084 : ScExternalRefManager* ScDocument::GetExternalRefManager() const
578 : {
579 8084 : ScDocument* pThis = const_cast<ScDocument*>(this);
580 8084 : if (!pExternalRefMgr.get())
581 732 : pThis->pExternalRefMgr.reset( new ScExternalRefManager( pThis));
582 :
583 8084 : return pExternalRefMgr.get();
584 : }
585 :
586 140 : bool ScDocument::IsInExternalReferenceMarking() const
587 : {
588 140 : return pExternalRefMgr.get() && pExternalRefMgr->isInReferenceMarking();
589 : }
590 :
591 0 : void ScDocument::MarkUsedExternalReferences()
592 : {
593 0 : if (!pExternalRefMgr.get())
594 0 : return;
595 0 : if (!pExternalRefMgr->hasExternalData())
596 0 : return;
597 : // Charts.
598 0 : pExternalRefMgr->markUsedByLinkListeners();
599 : // Formula cells.
600 0 : pExternalRefMgr->markUsedExternalRefCells();
601 :
602 : /* NOTE: Conditional formats and validation objects are marked when
603 : * collecting them during export. */
604 : }
605 :
606 0 : ScFormulaParserPool& ScDocument::GetFormulaParserPool() const
607 : {
608 0 : if( !mxFormulaParserPool.get() )
609 0 : mxFormulaParserPool.reset( new ScFormulaParserPool( *this ) );
610 0 : return *mxFormulaParserPool;
611 : }
612 :
613 4118 : const ScSheetEvents* ScDocument::GetSheetEvents( SCTAB nTab ) const
614 : {
615 4118 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
616 4118 : return maTabs[nTab]->GetSheetEvents();
617 0 : return NULL;
618 : }
619 :
620 44 : void ScDocument::SetSheetEvents( SCTAB nTab, const ScSheetEvents* pNew )
621 : {
622 44 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
623 44 : maTabs[nTab]->SetSheetEvents( pNew );
624 44 : }
625 :
626 82974 : bool ScDocument::HasSheetEventScript( SCTAB nTab, sal_Int32 nEvent, bool bWithVbaEvents ) const
627 : {
628 82974 : if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
629 : {
630 : // check if any event handler script has been configured
631 82974 : const ScSheetEvents* pEvents = maTabs[nTab]->GetSheetEvents();
632 82974 : if ( pEvents && pEvents->GetScript( nEvent ) )
633 0 : return true;
634 : // check if VBA event handlers exist
635 82974 : if (bWithVbaEvents && mxVbaEvents.is()) try
636 : {
637 738 : uno::Sequence< uno::Any > aArgs( 1 );
638 738 : aArgs[ 0 ] <<= nTab;
639 2776 : if (mxVbaEvents->hasVbaEventHandler( ScSheetEvents::GetVbaSheetEventId( nEvent ), aArgs ) ||
640 2688 : mxVbaEvents->hasVbaEventHandler( ScSheetEvents::GetVbaDocumentEventId( nEvent ), uno::Sequence< uno::Any >() ))
641 88 : return true;
642 : }
643 88 : catch( uno::Exception& )
644 : {
645 : }
646 : }
647 82974 : return false;
648 : }
649 :
650 60628 : bool ScDocument::HasAnySheetEventScript( sal_Int32 nEvent, bool bWithVbaEvents ) const
651 : {
652 60628 : SCTAB nSize = static_cast<SCTAB>(maTabs.size());
653 143602 : for (SCTAB nTab = 0; nTab < nSize; nTab++)
654 82974 : if (HasSheetEventScript( nTab, nEvent, bWithVbaEvents ))
655 0 : return true;
656 60628 : return false;
657 : }
658 :
659 8554 : bool ScDocument::HasAnyCalcNotification() const
660 : {
661 8554 : SCTAB nSize = static_cast<SCTAB>(maTabs.size());
662 35518 : for (SCTAB nTab = 0; nTab < nSize; nTab++)
663 26964 : if (maTabs[nTab] && maTabs[nTab]->GetCalcNotification())
664 0 : return true;
665 8554 : return false;
666 : }
667 :
668 0 : bool ScDocument::HasCalcNotification( SCTAB nTab ) const
669 : {
670 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
671 0 : return maTabs[nTab]->GetCalcNotification();
672 0 : return false;
673 : }
674 :
675 0 : void ScDocument::SetCalcNotification( SCTAB nTab )
676 : {
677 : // set only if not set before
678 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && !maTabs[nTab]->GetCalcNotification())
679 0 : maTabs[nTab]->SetCalcNotification(true);
680 0 : }
681 :
682 0 : void ScDocument::ResetCalcNotifications()
683 : {
684 0 : SCTAB nSize = static_cast<SCTAB>(maTabs.size());
685 0 : for (SCTAB nTab = 0; nTab < nSize; nTab++)
686 0 : if (maTabs[nTab] && maTabs[nTab]->GetCalcNotification())
687 0 : maTabs[nTab]->SetCalcNotification(false);
688 0 : }
689 :
690 19932 : ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, bool bCreate )
691 : {
692 19932 : ScOutlineTable* pVal = NULL;
693 :
694 19932 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
695 19932 : if (maTabs[nTab])
696 : {
697 19932 : pVal = maTabs[nTab]->GetOutlineTable();
698 19932 : if (!pVal)
699 15636 : if (bCreate)
700 : {
701 420 : maTabs[nTab]->StartOutlineTable();
702 420 : pVal = maTabs[nTab]->GetOutlineTable();
703 : }
704 : }
705 :
706 19932 : return pVal;
707 : }
708 :
709 8 : bool ScDocument::SetOutlineTable( SCTAB nTab, const ScOutlineTable* pNewOutline )
710 : {
711 8 : return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->SetOutlineTable(pNewOutline);
712 : }
713 :
714 2 : void ScDocument::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow,
715 : SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
716 : {
717 2 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
718 2 : maTabs[nTab]->DoAutoOutline( nStartCol, nStartRow, nEndCol, nEndRow );
719 2 : }
720 :
721 4 : bool ScDocument::TestRemoveSubTotals( SCTAB nTab, const ScSubTotalParam& rParam )
722 : {
723 4 : return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->TestRemoveSubTotals( rParam );
724 : }
725 :
726 4 : void ScDocument::RemoveSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
727 : {
728 4 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
729 4 : maTabs[nTab]->RemoveSubTotals( rParam );
730 4 : }
731 :
732 2 : bool ScDocument::DoSubTotals( SCTAB nTab, ScSubTotalParam& rParam )
733 : {
734 2 : return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->DoSubTotals( rParam );
735 : }
736 :
737 0 : bool ScDocument::HasSubTotalCells( const ScRange& rRange )
738 : {
739 0 : ScCellIterator aIter( this, rRange );
740 0 : for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
741 : {
742 0 : if (aIter.getType() != CELLTYPE_FORMULA)
743 0 : continue;
744 :
745 0 : if (aIter.getFormulaCell()->IsSubTotal())
746 0 : return true;
747 : }
748 0 : return false; // none found
749 : }
750 :
751 : /**
752 : * From this document this method copies the cells of positions at which
753 : * there are also cells in pPosDoc to pDestDoc
754 : */
755 0 : void ScDocument::CopyUpdated( ScDocument* pPosDoc, ScDocument* pDestDoc )
756 : {
757 0 : SCTAB nCount = static_cast<SCTAB>(maTabs.size());
758 0 : for (SCTAB nTab=0; nTab<nCount; nTab++)
759 0 : if (maTabs[nTab] && pPosDoc->maTabs[nTab] && pDestDoc->maTabs[nTab])
760 0 : maTabs[nTab]->CopyUpdated( pPosDoc->maTabs[nTab], pDestDoc->maTabs[nTab] );
761 0 : }
762 :
763 2 : void ScDocument::CopyScenario( SCTAB nSrcTab, SCTAB nDestTab, bool bNewScenario )
764 : {
765 6 : if (ValidTab(nSrcTab) && ValidTab(nDestTab) && nSrcTab < static_cast<SCTAB>(maTabs.size())
766 4 : && nDestTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab] && maTabs[nDestTab])
767 : {
768 : // Set flags correctly for active scenarios
769 : // and write current values back to recently active scenarios
770 2 : ScRangeList aRanges = *maTabs[nSrcTab]->GetScenarioRanges();
771 :
772 : // nDestTab is the target table
773 8 : for ( SCTAB nTab = nDestTab+1;
774 4 : nTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsScenario();
775 : nTab++ )
776 : {
777 2 : if ( maTabs[nTab]->IsActiveScenario() ) // Even if it's the same scenario
778 : {
779 0 : bool bTouched = false;
780 0 : for ( size_t nR=0, nRangeCount = aRanges.size(); nR < nRangeCount && !bTouched; nR++ )
781 : {
782 0 : const ScRange* pRange = aRanges[ nR ];
783 0 : if ( maTabs[nTab]->HasScenarioRange( *pRange ) )
784 0 : bTouched = true;
785 : }
786 0 : if (bTouched)
787 : {
788 0 : maTabs[nTab]->SetActiveScenario(false);
789 0 : if ( maTabs[nTab]->GetScenarioFlags() & SC_SCENARIO_TWOWAY )
790 0 : maTabs[nTab]->CopyScenarioFrom( maTabs[nDestTab] );
791 : }
792 : }
793 : }
794 :
795 2 : maTabs[nSrcTab]->SetActiveScenario(true); // This is where it's from ...
796 2 : if (!bNewScenario) // Copy data from the selected scenario
797 : {
798 0 : sc::AutoCalcSwitch aACSwitch(*this, false);
799 0 : maTabs[nSrcTab]->CopyScenarioTo( maTabs[nDestTab] );
800 :
801 0 : sc::SetFormulaDirtyContext aCxt;
802 0 : SetAllFormulasDirty(aCxt);
803 2 : }
804 : }
805 2 : }
806 :
807 0 : void ScDocument::MarkScenario( SCTAB nSrcTab, SCTAB nDestTab, ScMarkData& rDestMark,
808 : bool bResetMark, sal_uInt16 nNeededBits ) const
809 : {
810 0 : if (bResetMark)
811 0 : rDestMark.ResetMark();
812 :
813 0 : if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab])
814 0 : maTabs[nSrcTab]->MarkScenarioIn( rDestMark, nNeededBits );
815 :
816 0 : rDestMark.SetAreaTab( nDestTab );
817 0 : }
818 :
819 0 : bool ScDocument::HasScenarioRange( SCTAB nTab, const ScRange& rRange ) const
820 : {
821 0 : return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->HasScenarioRange( rRange );
822 : }
823 :
824 0 : const ScRangeList* ScDocument::GetScenarioRanges( SCTAB nTab ) const
825 : {
826 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
827 0 : return maTabs[nTab]->GetScenarioRanges();
828 :
829 0 : return NULL;
830 : }
831 :
832 0 : bool ScDocument::IsActiveScenario( SCTAB nTab ) const
833 : {
834 0 : return ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsActiveScenario( );
835 : }
836 :
837 0 : void ScDocument::SetActiveScenario( SCTAB nTab, bool bActive )
838 : {
839 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
840 0 : maTabs[nTab]->SetActiveScenario( bActive );
841 0 : }
842 :
843 0 : bool ScDocument::TestCopyScenario( SCTAB nSrcTab, SCTAB nDestTab ) const
844 : {
845 0 : if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size())
846 0 : && nDestTab < static_cast<SCTAB>(maTabs.size())&& ValidTab(nDestTab))
847 0 : return maTabs[nSrcTab]->TestCopyScenarioTo( maTabs[nDestTab] );
848 :
849 : OSL_FAIL("wrong table at TestCopyScenario");
850 0 : return false;
851 : }
852 :
853 93006 : void ScDocument::AddUnoObject( SfxListener& rObject )
854 : {
855 93006 : if (!pUnoBroadcaster)
856 2248 : pUnoBroadcaster = new SfxBroadcaster;
857 :
858 93006 : rObject.StartListening( *pUnoBroadcaster );
859 93006 : }
860 :
861 81515 : void ScDocument::RemoveUnoObject( SfxListener& rObject )
862 : {
863 81515 : if (pUnoBroadcaster)
864 : {
865 81515 : rObject.EndListening( *pUnoBroadcaster );
866 :
867 81515 : if ( bInUnoBroadcast )
868 : {
869 : // Broadcasts from ScDocument::BroadcastUno are the only way that
870 : // uno object methods are called without holding a reference.
871 : //
872 : // If RemoveUnoObject is called from an object dtor in the finalizer thread
873 : // while the main thread is calling BroadcastUno, the dtor thread must wait
874 : // (or the object's Notify might try to access a deleted object).
875 : // The SolarMutex can't be locked here because if a component is called from
876 : // a VCL event, the main thread has the SolarMutex locked all the time.
877 : //
878 : // This check is done after calling EndListening, so a later BroadcastUno call
879 : // won't touch this object.
880 :
881 0 : vcl::SolarMutexTryAndBuyGuard g;
882 0 : if (g.isAcquired())
883 : {
884 : // BroadcastUno is always called with the SolarMutex locked, so if it
885 : // can be acquired, this is within the same thread (should not happen)
886 : OSL_FAIL( "RemoveUnoObject called from BroadcastUno" );
887 : }
888 : else
889 : {
890 : // Let the thread that called BroadcastUno continue
891 0 : while ( bInUnoBroadcast )
892 : {
893 0 : osl::Thread::yield();
894 : }
895 0 : }
896 : }
897 : }
898 : else
899 : {
900 : OSL_FAIL("No Uno broadcaster");
901 : }
902 81515 : }
903 :
904 63594 : void ScDocument::BroadcastUno( const SfxHint &rHint )
905 : {
906 63594 : if (pUnoBroadcaster)
907 : {
908 63594 : bInUnoBroadcast = true;
909 63594 : pUnoBroadcaster->Broadcast( rHint );
910 63594 : bInUnoBroadcast = false;
911 :
912 : // During Broadcast notification, Uno objects can add to pUnoListenerCalls.
913 : // The listener calls must be processed after completing the broadcast,
914 : // because they can add or remove objects from pUnoBroadcaster.
915 :
916 63594 : const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
917 63774 : if ( pUnoListenerCalls && pSimpleHint &&
918 63774 : pSimpleHint->GetId() == SFX_HINT_DATACHANGED &&
919 90 : !bInUnoListenerCall )
920 : {
921 : // Listener calls may lead to BroadcastUno calls again. The listener calls
922 : // are not nested, instead the calls are collected in the list, and the
923 : // outermost call executes them all.
924 :
925 90 : ScChartLockGuard aChartLockGuard(this);
926 90 : bInUnoListenerCall = true;
927 90 : pUnoListenerCalls->ExecuteAndClear();
928 90 : bInUnoListenerCall = false;
929 : }
930 : }
931 63594 : }
932 :
933 64 : void ScDocument::AddUnoListenerCall( const uno::Reference<util::XModifyListener>& rListener,
934 : const lang::EventObject& rEvent )
935 : {
936 : OSL_ENSURE( bInUnoBroadcast, "AddUnoListenerCall is supposed to be called from BroadcastUno only" );
937 :
938 64 : if ( !pUnoListenerCalls )
939 18 : pUnoListenerCalls = new ScUnoListenerCalls;
940 64 : pUnoListenerCalls->Add( rListener, rEvent );
941 64 : }
942 :
943 122 : void ScDocument::BeginUnoRefUndo()
944 : {
945 : OSL_ENSURE( !pUnoRefUndoList, "BeginUnoRefUndo twice" );
946 122 : delete pUnoRefUndoList;
947 :
948 122 : pUnoRefUndoList = new ScUnoRefList;
949 122 : }
950 :
951 122 : ScUnoRefList* ScDocument::EndUnoRefUndo()
952 : {
953 122 : ScUnoRefList* pRet = pUnoRefUndoList;
954 122 : pUnoRefUndoList = NULL;
955 122 : return pRet; // Must be deleted by caller!
956 : }
957 :
958 3270 : void ScDocument::AddUnoRefChange( sal_Int64 nId, const ScRangeList& rOldRanges )
959 : {
960 3270 : if ( pUnoRefUndoList )
961 3270 : pUnoRefUndoList->Add( nId, rOldRanges );
962 3270 : }
963 :
964 418 : void ScDocument::UpdateReference(
965 : sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, bool bIncludeDraw, bool bUpdateNoteCaptionPos )
966 : {
967 418 : if (!ValidRange(rCxt.maRange))
968 418 : return;
969 :
970 418 : boost::scoped_ptr<sc::ExpandRefsSwitch> pExpandRefsSwitch;
971 418 : if (rCxt.isInserted())
972 170 : pExpandRefsSwitch.reset(new sc::ExpandRefsSwitch(*this, SC_MOD()->GetInputOptions().GetExpandRefs()));
973 :
974 : size_t nFirstTab, nLastTab;
975 418 : if (rCxt.meMode == URM_COPY)
976 : {
977 72 : nFirstTab = rCxt.maRange.aStart.Tab();
978 72 : nLastTab = rCxt.maRange.aEnd.Tab();
979 : }
980 : else
981 : {
982 : // TODO: Have these methods use the context object directly.
983 346 : ScRange aRange = rCxt.maRange;
984 346 : UpdateRefMode eUpdateRefMode = rCxt.meMode;
985 346 : SCCOL nDx = rCxt.mnColDelta;
986 346 : SCROW nDy = rCxt.mnRowDelta;
987 346 : SCTAB nDz = rCxt.mnTabDelta;
988 346 : SCCOL nCol1 = rCxt.maRange.aStart.Col(), nCol2 = rCxt.maRange.aEnd.Col();
989 346 : SCROW nRow1 = rCxt.maRange.aStart.Row(), nRow2 = rCxt.maRange.aEnd.Row();
990 346 : SCTAB nTab1 = rCxt.maRange.aStart.Tab(), nTab2 = rCxt.maRange.aEnd.Tab();
991 :
992 346 : xColNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
993 346 : xRowNameRanges->UpdateReference( eUpdateRefMode, this, aRange, nDx, nDy, nDz );
994 346 : pDBCollection->UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
995 346 : if (pRangeName)
996 154 : pRangeName->UpdateReference(rCxt, -1);
997 346 : if ( pDPCollection )
998 122 : pDPCollection->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz );
999 346 : UpdateChartRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz );
1000 346 : UpdateRefAreaLinks( eUpdateRefMode, aRange, nDx, nDy, nDz );
1001 346 : if ( pValidationList )
1002 14 : pValidationList->UpdateReference(rCxt);
1003 346 : if ( pDetOpList )
1004 0 : pDetOpList->UpdateReference( this, eUpdateRefMode, aRange, nDx, nDy, nDz );
1005 346 : if ( pUnoBroadcaster )
1006 : pUnoBroadcaster->Broadcast( ScUpdateRefHint(
1007 346 : eUpdateRefMode, aRange, nDx, nDy, nDz ) );
1008 :
1009 346 : nFirstTab = 0;
1010 346 : nLastTab = maTabs.size()-1;
1011 : }
1012 :
1013 878 : for (size_t i = nFirstTab, n = maTabs.size() ; i <= nLastTab && i < n; ++i)
1014 : {
1015 460 : if (!maTabs[i])
1016 0 : continue;
1017 :
1018 460 : maTabs[i]->UpdateReference(rCxt, pUndoDoc, bIncludeDraw, bUpdateNoteCaptionPos);
1019 : }
1020 :
1021 418 : if ( bIsEmbedded )
1022 : {
1023 : SCCOL theCol1;
1024 : SCROW theRow1;
1025 : SCTAB theTab1;
1026 : SCCOL theCol2;
1027 : SCROW theRow2;
1028 : SCTAB theTab2;
1029 0 : theCol1 = aEmbedRange.aStart.Col();
1030 0 : theRow1 = aEmbedRange.aStart.Row();
1031 0 : theTab1 = aEmbedRange.aStart.Tab();
1032 0 : theCol2 = aEmbedRange.aEnd.Col();
1033 0 : theRow2 = aEmbedRange.aEnd.Row();
1034 0 : theTab2 = aEmbedRange.aEnd.Tab();
1035 :
1036 : // TODO: Have ScRefUpdate::Update() use the context object directly.
1037 0 : UpdateRefMode eUpdateRefMode = rCxt.meMode;
1038 0 : SCCOL nDx = rCxt.mnColDelta;
1039 0 : SCROW nDy = rCxt.mnRowDelta;
1040 0 : SCTAB nDz = rCxt.mnTabDelta;
1041 0 : SCCOL nCol1 = rCxt.maRange.aStart.Col(), nCol2 = rCxt.maRange.aEnd.Col();
1042 0 : SCROW nRow1 = rCxt.maRange.aStart.Row(), nRow2 = rCxt.maRange.aEnd.Row();
1043 0 : SCTAB nTab1 = rCxt.maRange.aStart.Tab(), nTab2 = rCxt.maRange.aEnd.Tab();
1044 :
1045 0 : if ( ScRefUpdate::Update( this, eUpdateRefMode, nCol1,nRow1,nTab1, nCol2,nRow2,nTab2,
1046 0 : nDx,nDy,nDz, theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 ) )
1047 : {
1048 0 : aEmbedRange = ScRange( theCol1,theRow1,theTab1, theCol2,theRow2,theTab2 );
1049 : }
1050 : }
1051 :
1052 : // After moving, no clipboard move ref-updates are possible
1053 418 : if (rCxt.meMode != URM_COPY && IsClipboardSource())
1054 : {
1055 0 : ScDocument* pClipDoc = SC_MOD()->GetClipDoc();
1056 0 : if (pClipDoc)
1057 0 : pClipDoc->GetClipParam().mbCutMode = false;
1058 418 : }
1059 : }
1060 :
1061 0 : void ScDocument::UpdateTranspose( const ScAddress& rDestPos, ScDocument* pClipDoc,
1062 : const ScMarkData& rMark, ScDocument* pUndoDoc )
1063 : {
1064 : OSL_ENSURE(pClipDoc->bIsClip, "UpdateTranspose: No Clip");
1065 :
1066 0 : ScRange aSource;
1067 0 : ScClipParam& rClipParam = GetClipParam();
1068 0 : if (!rClipParam.maRanges.empty())
1069 0 : aSource = *rClipParam.maRanges.front();
1070 0 : ScAddress aDest = rDestPos;
1071 :
1072 0 : SCTAB nClipTab = 0;
1073 0 : for (SCTAB nDestTab=0; nDestTab< static_cast<SCTAB>(maTabs.size()) && maTabs[nDestTab]; nDestTab++)
1074 0 : if (rMark.GetTableSelect(nDestTab))
1075 : {
1076 0 : while (!pClipDoc->maTabs[nClipTab]) nClipTab = (nClipTab+1) % (MAXTAB+1);
1077 0 : aSource.aStart.SetTab( nClipTab );
1078 0 : aSource.aEnd.SetTab( nClipTab );
1079 0 : aDest.SetTab( nDestTab );
1080 :
1081 : // Like UpdateReference
1082 0 : if (pRangeName)
1083 0 : pRangeName->UpdateTranspose( aSource, aDest ); // Before the cells!
1084 0 : for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++)
1085 0 : if (maTabs[i])
1086 0 : maTabs[i]->UpdateTranspose( aSource, aDest, pUndoDoc );
1087 :
1088 0 : nClipTab = (nClipTab+1) % (MAXTAB+1);
1089 : }
1090 0 : }
1091 :
1092 0 : void ScDocument::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
1093 : {
1094 : //! pDBCollection
1095 : //! pPivotCollection
1096 : //! UpdateChartRef
1097 :
1098 0 : if (pRangeName)
1099 0 : pRangeName->UpdateGrow( rArea, nGrowX, nGrowY );
1100 :
1101 0 : for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()) && maTabs[i]; i++)
1102 0 : maTabs[i]->UpdateGrow( rArea, nGrowX, nGrowY );
1103 0 : }
1104 :
1105 46 : void ScDocument::Fill(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScProgress* pProgress, const ScMarkData& rMark,
1106 : sal_uLong nFillCount, FillDir eFillDir, FillCmd eFillCmd, FillDateCmd eFillDateCmd,
1107 : double nStepValue, double nMaxValue)
1108 : {
1109 46 : PutInOrder( nCol1, nCol2 );
1110 46 : PutInOrder( nRow1, nRow2 );
1111 46 : SCTAB nMax = maTabs.size();
1112 46 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1113 92 : for (; itr != itrEnd && *itr < nMax; ++itr)
1114 46 : if (maTabs[*itr])
1115 46 : maTabs[*itr]->Fill(nCol1, nRow1, nCol2, nRow2,
1116 : nFillCount, eFillDir, eFillCmd, eFillDateCmd,
1117 92 : nStepValue, nMaxValue, pProgress);
1118 46 : }
1119 :
1120 0 : OUString ScDocument::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW nEndY )
1121 : {
1122 0 : SCTAB nTab = rSource.aStart.Tab();
1123 0 : if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
1124 0 : return maTabs[nTab]->GetAutoFillPreview( rSource, nEndX, nEndY );
1125 :
1126 0 : return OUString();
1127 : }
1128 :
1129 0 : void ScDocument::AutoFormat( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1130 : sal_uInt16 nFormatNo, const ScMarkData& rMark )
1131 : {
1132 0 : PutInOrder( nStartCol, nEndCol );
1133 0 : PutInOrder( nStartRow, nEndRow );
1134 0 : SCTAB nMax = maTabs.size();
1135 0 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1136 0 : for (; itr != itrEnd && *itr < nMax; ++itr)
1137 0 : if (maTabs[*itr])
1138 0 : maTabs[*itr]->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo );
1139 0 : }
1140 :
1141 0 : void ScDocument::GetAutoFormatData(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1142 : ScAutoFormatData& rData)
1143 : {
1144 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
1145 : {
1146 0 : if (maTabs[nTab])
1147 : {
1148 0 : PutInOrder(nStartCol, nEndCol);
1149 0 : PutInOrder(nStartRow, nEndRow);
1150 0 : maTabs[nTab]->GetAutoFormatData(nStartCol, nStartRow, nEndCol, nEndRow, rData);
1151 : }
1152 : }
1153 0 : }
1154 :
1155 58 : void ScDocument::GetSearchAndReplaceStart( const SvxSearchItem& rSearchItem,
1156 : SCCOL& rCol, SCROW& rRow )
1157 : {
1158 58 : sal_uInt16 nCommand = rSearchItem.GetCommand();
1159 58 : bool bReplace = ( nCommand == SVX_SEARCHCMD_REPLACE ||
1160 58 : nCommand == SVX_SEARCHCMD_REPLACE_ALL );
1161 58 : if ( rSearchItem.GetBackward() )
1162 : {
1163 0 : if ( rSearchItem.GetRowDirection() )
1164 : {
1165 0 : if ( rSearchItem.GetPattern() )
1166 : {
1167 0 : rCol = MAXCOL;
1168 0 : rRow = MAXROW+1;
1169 : }
1170 0 : else if ( bReplace )
1171 : {
1172 0 : rCol = MAXCOL;
1173 0 : rRow = MAXROW;
1174 : }
1175 : else
1176 : {
1177 0 : rCol = MAXCOL+1;
1178 0 : rRow = MAXROW;
1179 : }
1180 : }
1181 : else
1182 : {
1183 0 : if ( rSearchItem.GetPattern() )
1184 : {
1185 0 : rCol = MAXCOL+1;
1186 0 : rRow = MAXROW;
1187 : }
1188 0 : else if ( bReplace )
1189 : {
1190 0 : rCol = MAXCOL;
1191 0 : rRow = MAXROW;
1192 : }
1193 : else
1194 : {
1195 0 : rCol = MAXCOL;
1196 0 : rRow = MAXROW+1;
1197 : }
1198 : }
1199 : }
1200 : else
1201 : {
1202 58 : if ( rSearchItem.GetRowDirection() )
1203 : {
1204 0 : if ( rSearchItem.GetPattern() )
1205 : {
1206 0 : rCol = 0;
1207 0 : rRow = (SCROW) -1;
1208 : }
1209 0 : else if ( bReplace )
1210 : {
1211 0 : rCol = 0;
1212 0 : rRow = 0;
1213 : }
1214 : else
1215 : {
1216 0 : rCol = (SCCOL) -1;
1217 0 : rRow = 0;
1218 : }
1219 : }
1220 : else
1221 : {
1222 58 : if ( rSearchItem.GetPattern() )
1223 : {
1224 0 : rCol = (SCCOL) -1;
1225 0 : rRow = 0;
1226 : }
1227 58 : else if ( bReplace )
1228 : {
1229 0 : rCol = 0;
1230 0 : rRow = 0;
1231 : }
1232 : else
1233 : {
1234 58 : rCol = 0;
1235 58 : rRow = (SCROW) -1;
1236 : }
1237 : }
1238 : }
1239 58 : }
1240 :
1241 144 : bool ScDocument::SearchAndReplace(
1242 : const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, SCTAB& rTab,
1243 : const ScMarkData& rMark, ScRangeList& rMatchedRanges,
1244 : OUString& rUndoStr, ScDocument* pUndoDoc)
1245 : {
1246 : // FIXME: Manage separated marks per table!
1247 144 : bool bFound = false;
1248 144 : if (rTab >= static_cast<SCTAB>(maTabs.size()))
1249 : OSL_FAIL("table out of range");
1250 144 : if (ValidTab(rTab))
1251 : {
1252 : SCCOL nCol;
1253 : SCROW nRow;
1254 : SCTAB nTab;
1255 144 : sal_uInt16 nCommand = rSearchItem.GetCommand();
1256 144 : if ( nCommand == SVX_SEARCHCMD_FIND_ALL ||
1257 : nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1258 : {
1259 98 : SCTAB nMax = maTabs.size();
1260 98 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1261 196 : for (; itr != itrEnd && *itr < nMax; ++itr)
1262 98 : if (maTabs[*itr])
1263 : {
1264 98 : nCol = 0;
1265 98 : nRow = 0;
1266 98 : bFound |= maTabs[*itr]->SearchAndReplace(
1267 98 : rSearchItem, nCol, nRow, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
1268 98 : }
1269 :
1270 : // Mark is set completely inside already
1271 : }
1272 : else
1273 : {
1274 46 : nCol = rCol;
1275 46 : nRow = rRow;
1276 46 : if (rSearchItem.GetBackward())
1277 : {
1278 0 : for (nTab = rTab; ((SCsTAB)nTab >= 0) && !bFound; nTab--)
1279 0 : if (maTabs[nTab])
1280 : {
1281 0 : if (rMark.GetTableSelect(nTab))
1282 : {
1283 0 : bFound = maTabs[nTab]->SearchAndReplace(
1284 0 : rSearchItem, nCol, nRow, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
1285 0 : if (bFound)
1286 : {
1287 0 : rCol = nCol;
1288 0 : rRow = nRow;
1289 0 : rTab = nTab;
1290 : }
1291 : else
1292 : ScDocument::GetSearchAndReplaceStart(
1293 0 : rSearchItem, nCol, nRow );
1294 : }
1295 : }
1296 : }
1297 : else
1298 : {
1299 110 : for (nTab = rTab; (nTab < static_cast<SCTAB>(maTabs.size())) && !bFound; nTab++)
1300 64 : if (maTabs[nTab])
1301 : {
1302 64 : if (rMark.GetTableSelect(nTab))
1303 : {
1304 46 : bFound = maTabs[nTab]->SearchAndReplace(
1305 46 : rSearchItem, nCol, nRow, rMark, rMatchedRanges, rUndoStr, pUndoDoc);
1306 46 : if (bFound)
1307 : {
1308 30 : rCol = nCol;
1309 30 : rRow = nRow;
1310 30 : rTab = nTab;
1311 : }
1312 : else
1313 : ScDocument::GetSearchAndReplaceStart(
1314 16 : rSearchItem, nCol, nRow );
1315 : }
1316 : }
1317 : }
1318 : }
1319 : }
1320 144 : return bFound;
1321 : }
1322 :
1323 : /**
1324 : * Adapt Outline
1325 : */
1326 2354 : bool ScDocument::UpdateOutlineCol( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bShow )
1327 : {
1328 2354 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1329 2354 : return maTabs[nTab]->UpdateOutlineCol( nStartCol, nEndCol, bShow );
1330 :
1331 : OSL_FAIL("missing tab");
1332 0 : return false;
1333 : }
1334 :
1335 58 : bool ScDocument::UpdateOutlineRow( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bShow )
1336 : {
1337 58 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1338 58 : return maTabs[nTab]->UpdateOutlineRow( nStartRow, nEndRow, bShow );
1339 :
1340 : OSL_FAIL("missing tab");
1341 0 : return false;
1342 : }
1343 :
1344 58 : void ScDocument::Sort(
1345 : SCTAB nTab, const ScSortParam& rSortParam, bool bKeepQuery, bool bUpdateRefs,
1346 : ScProgress* pProgress, sc::ReorderParam* pUndo )
1347 : {
1348 58 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1349 : {
1350 58 : bool bOldEnableIdle = IsIdleEnabled();
1351 58 : EnableIdle(false);
1352 58 : maTabs[nTab]->Sort(rSortParam, bKeepQuery, bUpdateRefs, pProgress, pUndo);
1353 58 : EnableIdle(bOldEnableIdle);
1354 : }
1355 58 : }
1356 :
1357 34 : void ScDocument::Reorder( const sc::ReorderParam& rParam, ScProgress* pProgress )
1358 : {
1359 34 : ScTable* pTab = FetchTable(rParam.maSortRange.aStart.Tab());
1360 34 : if (!pTab)
1361 34 : return;
1362 :
1363 34 : bool bOldEnableIdle = IsIdleEnabled();
1364 34 : EnableIdle(false);
1365 34 : pTab->Reorder(rParam, pProgress);
1366 34 : EnableIdle(bOldEnableIdle);
1367 : }
1368 :
1369 36 : SCSIZE ScDocument::Query(SCTAB nTab, const ScQueryParam& rQueryParam, bool bKeepSub)
1370 : {
1371 36 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1372 36 : return maTabs[nTab]->Query((ScQueryParam&)rQueryParam, bKeepSub);
1373 :
1374 : OSL_FAIL("missing tab");
1375 0 : return 0;
1376 : }
1377 :
1378 0 : void ScDocument::GetUpperCellString(SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rStr)
1379 : {
1380 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1381 0 : maTabs[nTab]->GetUpperCellString( nCol, nRow, rStr );
1382 : else
1383 0 : rStr = OUString();
1384 0 : }
1385 :
1386 2 : bool ScDocument::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, ScQueryParam& rQueryParam)
1387 : {
1388 2 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1389 2 : return maTabs[nTab]->CreateQueryParam(nCol1, nRow1, nCol2, nRow2, rQueryParam);
1390 :
1391 : OSL_FAIL("missing tab");
1392 0 : return false;
1393 : }
1394 :
1395 0 : bool ScDocument::HasAutoFilter( SCCOL nCurCol, SCROW nCurRow, SCTAB nCurTab )
1396 : {
1397 0 : const ScDBData* pDBData = GetDBAtCursor( nCurCol, nCurRow, nCurTab );
1398 0 : bool bHasAutoFilter = (pDBData != NULL);
1399 :
1400 0 : if ( pDBData )
1401 : {
1402 0 : if ( pDBData->HasHeader() )
1403 : {
1404 : SCCOL nCol;
1405 : SCROW nRow;
1406 : sal_Int16 nFlag;
1407 :
1408 0 : ScQueryParam aParam;
1409 0 : pDBData->GetQueryParam( aParam );
1410 0 : nRow = aParam.nRow1;
1411 :
1412 0 : for ( nCol=aParam.nCol1; nCol<=aParam.nCol2 && bHasAutoFilter; nCol++ )
1413 : {
1414 : nFlag = static_cast<const ScMergeFlagAttr*>(
1415 0 : GetAttr( nCol, nRow, nCurTab, ATTR_MERGE_FLAG ))->
1416 0 : GetValue();
1417 :
1418 0 : if ( (nFlag & SC_MF_AUTO) == 0 )
1419 0 : bHasAutoFilter = false;
1420 0 : }
1421 : }
1422 : else
1423 0 : bHasAutoFilter = false;
1424 : }
1425 :
1426 0 : return bHasAutoFilter;
1427 : }
1428 :
1429 18 : bool ScDocument::HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1430 : SCTAB nTab )
1431 : {
1432 18 : return ValidTab(nTab) && maTabs[nTab] && maTabs[nTab]->HasColHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1433 : }
1434 :
1435 0 : bool ScDocument::HasRowHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1436 : SCTAB nTab )
1437 : {
1438 0 : return ValidTab(nTab) && maTabs[nTab] && maTabs[nTab]->HasRowHeader( nStartCol, nStartRow, nEndCol, nEndRow );
1439 : }
1440 :
1441 : /**
1442 : * Entries for AutoFilter listbox
1443 : */
1444 0 : bool ScDocument::GetFilterEntries(
1445 : SCCOL nCol, SCROW nRow, SCTAB nTab, bool bFilter, std::vector<ScTypedStrData>& rStrings, bool& rHasDates)
1446 : {
1447 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && pDBCollection )
1448 : {
1449 0 : ScDBData* pDBData = pDBCollection->GetDBAtCursor(nCol, nRow, nTab, false); //!??
1450 0 : if (pDBData)
1451 : {
1452 0 : pDBData->ExtendDataArea(this);
1453 : SCTAB nAreaTab;
1454 : SCCOL nStartCol;
1455 : SCROW nStartRow;
1456 : SCCOL nEndCol;
1457 : SCROW nEndRow;
1458 0 : pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow );
1459 :
1460 0 : if (pDBData->HasHeader())
1461 0 : ++nStartRow;
1462 :
1463 0 : ScQueryParam aParam;
1464 0 : pDBData->GetQueryParam( aParam );
1465 :
1466 : // Return all filter entries, if a filter condition is connected with a boolean OR
1467 0 : if ( bFilter )
1468 : {
1469 0 : SCSIZE nEntryCount = aParam.GetEntryCount();
1470 0 : for ( SCSIZE i = 0; i < nEntryCount && aParam.GetEntry(i).bDoQuery; ++i )
1471 : {
1472 0 : ScQueryEntry& rEntry = aParam.GetEntry(i);
1473 0 : if ( rEntry.eConnect != SC_AND )
1474 : {
1475 0 : bFilter = false;
1476 0 : break;
1477 : }
1478 : }
1479 : }
1480 :
1481 0 : if ( bFilter )
1482 : {
1483 0 : maTabs[nTab]->GetFilteredFilterEntries( nCol, nStartRow, nEndRow, aParam, rStrings, rHasDates );
1484 : }
1485 : else
1486 : {
1487 0 : maTabs[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
1488 : }
1489 :
1490 0 : sortAndRemoveDuplicates(rStrings, aParam.bCaseSens);
1491 0 : return true;
1492 : }
1493 : }
1494 :
1495 0 : return false;
1496 : }
1497 :
1498 : /**
1499 : * Entries for Filter dialog
1500 : */
1501 0 : bool ScDocument::GetFilterEntriesArea(
1502 : SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bCaseSens,
1503 : std::vector<ScTypedStrData>& rStrings, bool& rHasDates)
1504 : {
1505 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1506 : {
1507 0 : maTabs[nTab]->GetFilterEntries( nCol, nStartRow, nEndRow, rStrings, rHasDates );
1508 0 : sortAndRemoveDuplicates(rStrings, bCaseSens);
1509 0 : return true;
1510 : }
1511 :
1512 0 : return false;
1513 : }
1514 :
1515 : /**
1516 : * Entries for selection list listbox (no numbers/formulas)
1517 : */
1518 4 : bool ScDocument::GetDataEntries(
1519 : SCCOL nCol, SCROW nRow, SCTAB nTab, bool bCaseSens,
1520 : std::vector<ScTypedStrData>& rStrings, bool bLimit )
1521 : {
1522 4 : if( !bLimit )
1523 : {
1524 : /* Try to generate the list from list validation. This part is skipped,
1525 : if bLimit==true, because in that case this function is called to get
1526 : cell values for auto completion on input. */
1527 4 : sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
1528 4 : if( nValidation )
1529 : {
1530 0 : const ScValidationData* pData = GetValidationEntry( nValidation );
1531 0 : if( pData && pData->FillSelectionList( rStrings, ScAddress( nCol, nRow, nTab ) ) )
1532 : {
1533 0 : if (pData->GetListType() == css::sheet::TableValidationVisibility::SORTEDASCENDING)
1534 0 : sortAndRemoveDuplicates(rStrings, bCaseSens);
1535 :
1536 0 : return true;
1537 : }
1538 : }
1539 : }
1540 :
1541 4 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()))
1542 0 : return false;
1543 :
1544 4 : if (!maTabs[nTab])
1545 0 : return false;
1546 :
1547 4 : std::set<ScTypedStrData> aStrings;
1548 4 : bool bRet = maTabs[nTab]->GetDataEntries(nCol, nRow, aStrings, bLimit);
1549 4 : rStrings.insert(rStrings.end(), aStrings.begin(), aStrings.end());
1550 4 : sortAndRemoveDuplicates(rStrings, bCaseSens);
1551 :
1552 4 : return bRet;
1553 : }
1554 :
1555 : /**
1556 : * Entries for Formula auto input
1557 : */
1558 0 : bool ScDocument::GetFormulaEntries( ScTypedCaseStrSet& rStrings )
1559 : {
1560 :
1561 : // Range name
1562 0 : if ( pRangeName )
1563 : {
1564 0 : ScRangeName::const_iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
1565 0 : for (; itr != itrEnd; ++itr)
1566 0 : rStrings.insert(ScTypedStrData(itr->second->GetName(), 0.0, ScTypedStrData::Name));
1567 : }
1568 :
1569 : // Database collection
1570 0 : if ( pDBCollection )
1571 : {
1572 0 : const ScDBCollection::NamedDBs& rDBs = pDBCollection->getNamedDBs();
1573 0 : ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
1574 0 : for (; itr != itrEnd; ++itr)
1575 0 : rStrings.insert(ScTypedStrData(itr->GetName(), 0.0, ScTypedStrData::DbName));
1576 : }
1577 :
1578 : // Content of name ranges
1579 : ScRangePairList* pLists[2];
1580 0 : pLists[0] = GetColNameRanges();
1581 0 : pLists[1] = GetRowNameRanges();
1582 0 : for (sal_uInt16 nListNo=0; nListNo<2; nListNo++)
1583 : {
1584 0 : ScRangePairList* pList = pLists[ nListNo ];
1585 0 : if (!pList)
1586 0 : continue;
1587 :
1588 0 : for ( size_t i = 0, nPairs = pList->size(); i < nPairs; ++i )
1589 : {
1590 0 : ScRangePair* pPair = (*pList)[i];
1591 0 : ScRange aRange = pPair->GetRange(0);
1592 0 : ScCellIterator aIter( this, aRange );
1593 0 : for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
1594 : {
1595 0 : if (!aIter.hasString())
1596 0 : continue;
1597 :
1598 0 : OUString aStr = aIter.getString();
1599 0 : rStrings.insert(ScTypedStrData(aStr, 0.0, ScTypedStrData::Header));
1600 0 : }
1601 0 : }
1602 : }
1603 :
1604 0 : return true;
1605 : }
1606 :
1607 0 : void ScDocument::GetEmbedded( ScRange& rRange ) const
1608 : {
1609 0 : rRange = aEmbedRange;
1610 0 : }
1611 :
1612 0 : Rectangle ScDocument::GetEmbeddedRect() const // 1/100 mm
1613 : {
1614 0 : Rectangle aRect;
1615 0 : ScTable* pTable = NULL;
1616 0 : if ( aEmbedRange.aStart.Tab() < static_cast<SCTAB>(maTabs.size()) )
1617 0 : pTable = maTabs[aEmbedRange.aStart.Tab()];
1618 : else
1619 : OSL_FAIL("table out of range");
1620 0 : if (!pTable)
1621 : {
1622 : OSL_FAIL("GetEmbeddedRect without a table");
1623 : }
1624 : else
1625 : {
1626 : SCCOL i;
1627 :
1628 0 : for (i=0; i<aEmbedRange.aStart.Col(); i++)
1629 0 : aRect.Left() += pTable->GetColWidth(i);
1630 0 : aRect.Top() += pTable->GetRowHeight( 0, aEmbedRange.aStart.Row() - 1);
1631 0 : aRect.Right() = aRect.Left();
1632 0 : for (i=aEmbedRange.aStart.Col(); i<=aEmbedRange.aEnd.Col(); i++)
1633 0 : aRect.Right() += pTable->GetColWidth(i);
1634 0 : aRect.Bottom() = aRect.Top();
1635 0 : aRect.Bottom() += pTable->GetRowHeight( aEmbedRange.aStart.Row(), aEmbedRange.aEnd.Row());
1636 :
1637 0 : aRect.Left() = (long) ( aRect.Left() * HMM_PER_TWIPS );
1638 0 : aRect.Right() = (long) ( aRect.Right() * HMM_PER_TWIPS );
1639 0 : aRect.Top() = (long) ( aRect.Top() * HMM_PER_TWIPS );
1640 0 : aRect.Bottom() = (long) ( aRect.Bottom() * HMM_PER_TWIPS );
1641 : }
1642 0 : return aRect;
1643 : }
1644 :
1645 0 : void ScDocument::SetEmbedded( const ScRange& rRange )
1646 : {
1647 0 : bIsEmbedded = true;
1648 0 : aEmbedRange = rRange;
1649 0 : }
1650 :
1651 0 : void ScDocument::ResetEmbedded()
1652 : {
1653 0 : bIsEmbedded = false;
1654 0 : aEmbedRange = ScRange();
1655 0 : }
1656 :
1657 : /** Similar to ScViewData::AddPixelsWhile(), but add height twips and only
1658 : while result is less than nStopTwips.
1659 : @return true if advanced at least one row.
1660 : */
1661 1884 : static bool lcl_AddTwipsWhile( long & rTwips, long nStopTwips, SCROW & rPosY, SCROW nEndRow, const ScTable * pTable, bool bHiddenAsZero = true )
1662 : {
1663 1884 : SCROW nRow = rPosY;
1664 1884 : bool bAdded = false;
1665 1884 : bool bStop = false;
1666 7526 : while (rTwips < nStopTwips && nRow <= nEndRow && !bStop)
1667 : {
1668 : SCROW nHeightEndRow;
1669 3758 : sal_uInt16 nHeight = pTable->GetRowHeight( nRow, NULL, &nHeightEndRow, bHiddenAsZero );
1670 3758 : if (nHeightEndRow > nEndRow)
1671 0 : nHeightEndRow = nEndRow;
1672 3758 : if (!nHeight)
1673 100 : nRow = nHeightEndRow + 1;
1674 : else
1675 : {
1676 3658 : SCROW nRows = nHeightEndRow - nRow + 1;
1677 3658 : sal_Int64 nAdd = static_cast<sal_Int64>(nHeight) * nRows;
1678 3658 : if (nAdd + rTwips >= nStopTwips)
1679 : {
1680 1870 : sal_Int64 nDiff = nAdd + rTwips - nStopTwips;
1681 1870 : nRows -= static_cast<SCROW>(nDiff / nHeight);
1682 1870 : nAdd = static_cast<sal_Int64>(nHeight) * nRows;
1683 : // We're looking for a value that satisfies loop condition.
1684 1870 : if (nAdd + rTwips >= nStopTwips)
1685 : {
1686 1870 : --nRows;
1687 1870 : nAdd -= nHeight;
1688 : }
1689 1870 : bStop = true;
1690 : }
1691 3658 : rTwips += static_cast<long>(nAdd);
1692 3658 : nRow += nRows;
1693 : }
1694 : }
1695 1884 : if (nRow > rPosY)
1696 : {
1697 1458 : --nRow;
1698 1458 : bAdded = true;
1699 : }
1700 1884 : rPosY = nRow;
1701 1884 : return bAdded;
1702 : }
1703 :
1704 942 : ScRange ScDocument::GetRange( SCTAB nTab, const Rectangle& rMMRect, bool bHiddenAsZero ) const
1705 : {
1706 942 : ScTable* pTable = NULL;
1707 942 : if (nTab < static_cast<SCTAB>(maTabs.size()))
1708 942 : pTable = maTabs[nTab];
1709 : else
1710 : OSL_FAIL("table out of range");
1711 942 : if (!pTable)
1712 : {
1713 : OSL_FAIL("GetRange without a table");
1714 0 : return ScRange();
1715 : }
1716 :
1717 942 : Rectangle aPosRect = rMMRect;
1718 942 : if ( IsNegativePage( nTab ) )
1719 0 : ScDrawLayer::MirrorRectRTL( aPosRect ); // Always with positive (LTR) values
1720 :
1721 : long nSize;
1722 : long nTwips;
1723 : long nAdd;
1724 : bool bEnd;
1725 :
1726 942 : nSize = 0;
1727 942 : nTwips = (long) (aPosRect.Left() / HMM_PER_TWIPS);
1728 :
1729 942 : SCCOL nX1 = 0;
1730 942 : bEnd = false;
1731 7494 : while (!bEnd)
1732 : {
1733 5610 : nAdd = (long) pTable->GetColWidth(nX1, bHiddenAsZero);
1734 5610 : if (nSize+nAdd <= nTwips+1 && nX1<MAXCOL)
1735 : {
1736 4668 : nSize += nAdd;
1737 4668 : ++nX1;
1738 : }
1739 : else
1740 942 : bEnd = true;
1741 : }
1742 :
1743 942 : nTwips = (long) (aPosRect.Right() / HMM_PER_TWIPS);
1744 :
1745 942 : SCCOL nX2 = nX1;
1746 942 : bEnd = false;
1747 6834 : while (!bEnd)
1748 : {
1749 4950 : nAdd = (long) pTable->GetColWidth(nX2, bHiddenAsZero);
1750 4950 : if (nSize+nAdd < nTwips && nX2<MAXCOL)
1751 : {
1752 4008 : nSize += nAdd;
1753 4008 : ++nX2;
1754 : }
1755 : else
1756 942 : bEnd = true;
1757 : }
1758 :
1759 942 : nSize = 0;
1760 942 : nTwips = (long) (aPosRect.Top() / HMM_PER_TWIPS);
1761 :
1762 942 : SCROW nY1 = 0;
1763 : // Was if(nSize+nAdd<=nTwips+1) inside loop => if(nSize+nAdd<nTwips+2)
1764 942 : if (lcl_AddTwipsWhile( nSize, nTwips+2, nY1, MAXROW, pTable, bHiddenAsZero) && nY1 < MAXROW)
1765 562 : ++nY1; // original loop ended on last matched +1 unless that was MAXROW
1766 :
1767 942 : nTwips = (long) (aPosRect.Bottom() / HMM_PER_TWIPS);
1768 :
1769 942 : SCROW nY2 = nY1;
1770 : // Was if(nSize+nAdd<nTwips) inside loop => if(nSize+nAdd<nTwips)
1771 942 : if (lcl_AddTwipsWhile( nSize, nTwips, nY2, MAXROW, pTable, bHiddenAsZero) && nY2 < MAXROW)
1772 896 : ++nY2; // original loop ended on last matched +1 unless that was MAXROW
1773 :
1774 942 : return ScRange( nX1,nY1,nTab, nX2,nY2,nTab );
1775 : }
1776 :
1777 0 : void ScDocument::SetEmbedded( SCTAB nTab, const Rectangle& rRect ) // From VisArea (1/100 mm)
1778 : {
1779 0 : bIsEmbedded = true;
1780 0 : aEmbedRange = GetRange( nTab, rRect );
1781 0 : }
1782 :
1783 96 : ScDocProtection* ScDocument::GetDocProtection() const
1784 : {
1785 96 : return pDocProtection.get();
1786 : }
1787 :
1788 6 : void ScDocument::SetDocProtection(const ScDocProtection* pProtect)
1789 : {
1790 6 : if (pProtect)
1791 4 : pDocProtection.reset(new ScDocProtection(*pProtect));
1792 : else
1793 2 : pDocProtection.reset();
1794 6 : }
1795 :
1796 184 : bool ScDocument::IsDocProtected() const
1797 : {
1798 184 : return pDocProtection.get() && pDocProtection->isProtected();
1799 : }
1800 :
1801 76 : bool ScDocument::IsDocEditable() const
1802 : {
1803 : // Import into read-only document is possible
1804 76 : return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() );
1805 : }
1806 :
1807 49352 : bool ScDocument::IsTabProtected( SCTAB nTab ) const
1808 : {
1809 49352 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
1810 49352 : return maTabs[nTab]->IsProtected();
1811 :
1812 : OSL_FAIL("Wrong table number");
1813 0 : return false;
1814 : }
1815 :
1816 300 : ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const
1817 : {
1818 300 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
1819 300 : return maTabs[nTab]->GetProtection();
1820 :
1821 0 : return NULL;
1822 : }
1823 :
1824 36 : void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect)
1825 : {
1826 36 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()))
1827 36 : return;
1828 :
1829 36 : maTabs[nTab]->SetProtection(pProtect);
1830 : }
1831 :
1832 0 : void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest)
1833 : {
1834 0 : if (!ValidTab(nTabSrc) || nTabSrc >= static_cast<SCTAB>(maTabs.size()) || nTabDest >= static_cast<SCTAB>(maTabs.size()) || !ValidTab(nTabDest))
1835 0 : return;
1836 :
1837 0 : maTabs[nTabDest]->SetProtection( maTabs[nTabSrc]->GetProtection() );
1838 : }
1839 :
1840 72007 : const ScDocOptions& ScDocument::GetDocOptions() const
1841 : {
1842 : assert(pDocOptions && "No DocOptions! :-(");
1843 72007 : return *pDocOptions;
1844 : }
1845 :
1846 4118 : void ScDocument::SetDocOptions( const ScDocOptions& rOpt )
1847 : {
1848 : assert(pDocOptions && "No DocOptions! :-(");
1849 :
1850 4118 : *pDocOptions = rOpt;
1851 4118 : xPoolHelper->SetFormTableOpt(rOpt);
1852 4118 : }
1853 :
1854 10566 : const ScViewOptions& ScDocument::GetViewOptions() const
1855 : {
1856 : assert(pViewOptions && "No ViewOptions! :-(");
1857 10566 : return *pViewOptions;
1858 : }
1859 :
1860 9550 : void ScDocument::SetViewOptions( const ScViewOptions& rOpt )
1861 : {
1862 : assert(pViewOptions && "No ViewOptions! :-(");
1863 9550 : *pViewOptions = rOpt;
1864 9550 : }
1865 :
1866 1870 : void ScDocument::GetLanguage( LanguageType& rLatin, LanguageType& rCjk, LanguageType& rCtl ) const
1867 : {
1868 1870 : rLatin = eLanguage;
1869 1870 : rCjk = eCjkLanguage;
1870 1870 : rCtl = eCtlLanguage;
1871 1870 : }
1872 :
1873 6028 : void ScDocument::SetLanguage( LanguageType eLatin, LanguageType eCjk, LanguageType eCtl )
1874 : {
1875 6028 : eLanguage = eLatin;
1876 6028 : eCjkLanguage = eCjk;
1877 6028 : eCtlLanguage = eCtl;
1878 6028 : if ( xPoolHelper.is() )
1879 : {
1880 4044 : ScDocumentPool* pPool = xPoolHelper->GetDocPool();
1881 4044 : pPool->SetPoolDefaultItem( SvxLanguageItem( eLanguage, ATTR_FONT_LANGUAGE ) );
1882 4044 : pPool->SetPoolDefaultItem( SvxLanguageItem( eCjkLanguage, ATTR_CJK_FONT_LANGUAGE ) );
1883 4044 : pPool->SetPoolDefaultItem( SvxLanguageItem( eCtlLanguage, ATTR_CTL_FONT_LANGUAGE ) );
1884 : }
1885 :
1886 6028 : UpdateDrawLanguages(); // Set edit engine defaults in drawing layer pool
1887 6028 : }
1888 :
1889 6290 : Rectangle ScDocument::GetMMRect( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, bool bHiddenAsZero ) const
1890 : {
1891 6290 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
1892 : {
1893 : OSL_FAIL("GetMMRect: wrong table");
1894 0 : return Rectangle(0,0,0,0);
1895 : }
1896 :
1897 : SCCOL i;
1898 6290 : Rectangle aRect;
1899 :
1900 25410 : for (i=0; i<nStartCol; i++)
1901 19120 : aRect.Left() += GetColWidth(i,nTab, bHiddenAsZero );
1902 6290 : aRect.Top() += GetRowHeight( 0, nStartRow-1, nTab, bHiddenAsZero );
1903 :
1904 6290 : aRect.Right() = aRect.Left();
1905 6290 : aRect.Bottom() = aRect.Top();
1906 :
1907 338774 : for (i=nStartCol; i<=nEndCol; i++)
1908 332484 : aRect.Right() += GetColWidth(i,nTab, bHiddenAsZero);
1909 6290 : aRect.Bottom() += GetRowHeight( nStartRow, nEndRow, nTab, bHiddenAsZero );
1910 :
1911 6290 : aRect.Left() = (long)(aRect.Left() * HMM_PER_TWIPS);
1912 6290 : aRect.Right() = (long)(aRect.Right() * HMM_PER_TWIPS);
1913 6290 : aRect.Top() = (long)(aRect.Top() * HMM_PER_TWIPS);
1914 6290 : aRect.Bottom() = (long)(aRect.Bottom() * HMM_PER_TWIPS);
1915 :
1916 6290 : if ( IsNegativePage( nTab ) )
1917 0 : ScDrawLayer::MirrorRectRTL( aRect );
1918 :
1919 6290 : return aRect;
1920 : }
1921 :
1922 150 : void ScDocument::SetExtDocOptions( ScExtDocOptions* pNewOptions )
1923 : {
1924 150 : delete pExtDocOptions;
1925 150 : pExtDocOptions = pNewOptions;
1926 150 : }
1927 :
1928 0 : void ScDocument::DoMergeContents( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1929 : SCCOL nEndCol, SCROW nEndRow )
1930 : {
1931 0 : OUString aEmpty;
1932 0 : OUStringBuffer aTotal;
1933 0 : OUString aCellStr;
1934 : SCCOL nCol;
1935 : SCROW nRow;
1936 0 : for (nRow=nStartRow; nRow<=nEndRow; nRow++)
1937 0 : for (nCol=nStartCol; nCol<=nEndCol; nCol++)
1938 : {
1939 0 : aCellStr = GetString(nCol, nRow, nTab);
1940 0 : if (!aCellStr.isEmpty())
1941 : {
1942 0 : if (!aTotal.isEmpty())
1943 0 : aTotal.append(' ');
1944 0 : aTotal.append(aCellStr);
1945 : }
1946 0 : if (nCol != nStartCol || nRow != nStartRow)
1947 0 : SetString(nCol,nRow,nTab,aEmpty);
1948 : }
1949 :
1950 0 : SetString(nStartCol,nStartRow,nTab,aTotal.makeStringAndClear());
1951 0 : }
1952 :
1953 1476 : void ScDocument::DoMerge( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
1954 : SCCOL nEndCol, SCROW nEndRow, bool bDeleteCaptions )
1955 : {
1956 1476 : ScMergeAttr aAttr( nEndCol-nStartCol+1, nEndRow-nStartRow+1 );
1957 1476 : ApplyAttr( nStartCol, nStartRow, nTab, aAttr );
1958 :
1959 1476 : if ( nEndCol > nStartCol )
1960 1446 : ApplyFlagsTab( nStartCol+1, nStartRow, nEndCol, nStartRow, nTab, SC_MF_HOR );
1961 1476 : if ( nEndRow > nStartRow )
1962 60 : ApplyFlagsTab( nStartCol, nStartRow+1, nStartCol, nEndRow, nTab, SC_MF_VER );
1963 1476 : if ( nEndCol > nStartCol && nEndRow > nStartRow )
1964 30 : ApplyFlagsTab( nStartCol+1, nStartRow+1, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1965 :
1966 : // Remove all covered notes (removed captions are collected by drawing undo if active)
1967 1476 : InsertDeleteFlags nDelFlag = IDF_NOTE | (bDeleteCaptions ? IDF_NONE : IDF_NOCAPTIONS);
1968 1476 : if( nStartCol < nEndCol )
1969 1446 : DeleteAreaTab( nStartCol + 1, nStartRow, nEndCol, nStartRow, nTab, nDelFlag );
1970 1476 : if( nStartRow < nEndRow )
1971 60 : DeleteAreaTab( nStartCol, nStartRow + 1, nEndCol, nEndRow, nTab, nDelFlag );
1972 1476 : }
1973 :
1974 0 : void ScDocument::RemoveMerge( SCCOL nCol, SCROW nRow, SCTAB nTab )
1975 : {
1976 : const ScMergeAttr* pAttr = static_cast<const ScMergeAttr*>(
1977 0 : GetAttr( nCol, nRow, nTab, ATTR_MERGE ));
1978 :
1979 0 : if ( pAttr->GetColMerge() <= 1 && pAttr->GetRowMerge() <= 1 )
1980 0 : return;
1981 :
1982 0 : SCCOL nEndCol = nCol + pAttr->GetColMerge() - 1;
1983 0 : SCROW nEndRow = nRow + pAttr->GetRowMerge() - 1;
1984 :
1985 0 : RemoveFlagsTab( nCol, nRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1986 :
1987 : const ScMergeAttr* pDefAttr = static_cast<const ScMergeAttr*>(
1988 0 : &xPoolHelper->GetDocPool()->GetDefaultItem( ATTR_MERGE ));
1989 0 : ApplyAttr( nCol, nRow, nTab, *pDefAttr );
1990 : }
1991 :
1992 60 : void ScDocument::ExtendPrintArea( OutputDevice* pDev, SCTAB nTab,
1993 : SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow ) const
1994 : {
1995 60 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1996 60 : maTabs[nTab]->ExtendPrintArea( pDev, nStartCol, nStartRow, rEndCol, nEndRow );
1997 60 : }
1998 :
1999 0 : SCSIZE ScDocument::GetPatternCount( SCTAB nTab, SCCOL nCol ) const
2000 : {
2001 0 : if( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
2002 0 : return maTabs[nTab]->GetPatternCount( nCol );
2003 : else
2004 0 : return 0;
2005 : }
2006 :
2007 0 : SCSIZE ScDocument::GetPatternCount( SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const
2008 : {
2009 0 : if( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
2010 0 : return maTabs[nTab]->GetPatternCount( nCol, nRow1, nRow2 );
2011 : else
2012 0 : return 0;
2013 : }
2014 :
2015 0 : bool ScDocument::ReservePatternCount( SCTAB nTab, SCCOL nCol, SCSIZE nReserve )
2016 : {
2017 0 : if( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
2018 0 : return maTabs[nTab]->ReservePatternCount( nCol, nReserve );
2019 : else
2020 0 : return false;
2021 : }
2022 :
2023 0 : void ScDocument::GetSortParam( ScSortParam& rParam, SCTAB nTab )
2024 : {
2025 0 : rParam = mSheetSortParams[ nTab ];
2026 0 : }
2027 :
2028 0 : void ScDocument::SetSortParam( ScSortParam& rParam, SCTAB nTab )
2029 : {
2030 0 : mSheetSortParams[ nTab ] = rParam;
2031 228 : }
2032 :
2033 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|