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