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 "scitems.hxx"
21 : #include <editeng/eeitem.hxx>
22 :
23 : #include <editeng/boxitem.hxx>
24 : #include <editeng/frmdiritem.hxx>
25 : #include <editeng/editobj.hxx>
26 : #include <svx/pageitem.hxx>
27 : #include <editeng/editeng.hxx>
28 : #include <svx/sdrundomanager.hxx>
29 : #include <svx/svditer.hxx>
30 : #include <svx/svdpage.hxx>
31 : #include <svx/svdocapt.hxx>
32 : #include <sfx2/app.hxx>
33 : #include <sfx2/objsh.hxx>
34 : #include <sfx2/docfile.hxx>
35 : #include <svl/poolcach.hxx>
36 : #include <unotools/saveopt.hxx>
37 : #include <svl/zforlist.hxx>
38 : #include <unotools/charclass.hxx>
39 : #include <unotools/transliterationwrapper.hxx>
40 : #include <tools/tenccvt.hxx>
41 : #include <tools/urlobj.hxx>
42 :
43 : #include <com/sun/star/text/WritingMode2.hpp>
44 : #include <com/sun/star/script/vba/XVBACompatibility.hpp>
45 : #include <com/sun/star/sheet/TablePageBreakData.hpp>
46 : #include <com/sun/star/lang/NotInitializedException.hpp>
47 :
48 : #include "document.hxx"
49 : #include "table.hxx"
50 : #include "column.hxx"
51 : #include "attrib.hxx"
52 : #include "attarray.hxx"
53 : #include "markarr.hxx"
54 : #include "patattr.hxx"
55 : #include "rangenam.hxx"
56 : #include "poolhelp.hxx"
57 : #include "docpool.hxx"
58 : #include "stlpool.hxx"
59 : #include "stlsheet.hxx"
60 : #include "globstr.hrc"
61 : #include "rechead.hxx"
62 : #include "dbdata.hxx"
63 : #include "pivot.hxx"
64 : #include "chartlis.hxx"
65 : #include "rangelst.hxx"
66 : #include "markdata.hxx"
67 : #include "drwlayer.hxx"
68 : #include "conditio.hxx"
69 : #include "colorscale.hxx"
70 : #include "validat.hxx"
71 : #include "prnsave.hxx"
72 : #include "chgtrack.hxx"
73 : #include "sc.hrc"
74 : #include "scresid.hxx"
75 : #include "hints.hxx"
76 : #include "detdata.hxx"
77 : #include "dpobject.hxx"
78 : #include "detfunc.hxx"
79 : #include "scmod.hxx"
80 : #include "dociter.hxx"
81 : #include "progress.hxx"
82 : #include "autonamecache.hxx"
83 : #include "bcaslot.hxx"
84 : #include "postit.hxx"
85 : #include "externalrefmgr.hxx"
86 : #include "tabprotection.hxx"
87 : #include "clipparam.hxx"
88 : #include "defaultsoptions.hxx"
89 : #include "editutil.hxx"
90 : #include "stringutil.hxx"
91 : #include "formulaiter.hxx"
92 : #include "formulacell.hxx"
93 : #include "clipcontext.hxx"
94 : #include "listenercontext.hxx"
95 : #include "scopetools.hxx"
96 : #include "refupdatecontext.hxx"
97 : #include "formulagroup.hxx"
98 : #include <tokenarray.hxx>
99 : #include <tokenstringcontext.hxx>
100 :
101 : #include <formula/vectortoken.hxx>
102 :
103 : #include <map>
104 : #include <limits>
105 : #include <boost/checked_delete.hpp>
106 : #include <boost/scoped_ptr.hpp>
107 :
108 : #include "mtvelements.hxx"
109 :
110 : using ::editeng::SvxBorderLine;
111 : using namespace ::com::sun::star;
112 :
113 : namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
114 : using ::com::sun::star::uno::Sequence;
115 : using ::com::sun::star::sheet::TablePageBreakData;
116 : using ::std::set;
117 :
118 : namespace {
119 :
120 78 : std::pair<SCTAB,SCTAB> getMarkedTableRange(const std::vector<ScTable*>& rTables, const ScMarkData& rMark)
121 : {
122 78 : SCTAB nTabStart = MAXTAB;
123 78 : SCTAB nTabEnd = 0;
124 78 : SCTAB nMax = static_cast<SCTAB>(rTables.size());
125 78 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
126 153 : for (; itr != itrEnd && *itr < nMax; ++itr)
127 : {
128 75 : if (!rTables[*itr])
129 0 : continue;
130 :
131 75 : if (*itr < nTabStart)
132 75 : nTabStart = *itr;
133 75 : nTabEnd = *itr;
134 : }
135 :
136 78 : return std::pair<SCTAB,SCTAB>(nTabStart,nTabEnd);
137 : }
138 :
139 : }
140 :
141 : struct ScDefaultAttr
142 : {
143 : const ScPatternAttr* pAttr;
144 : SCROW nFirst;
145 : SCSIZE nCount;
146 105 : ScDefaultAttr(const ScPatternAttr* pPatAttr) : pAttr(pPatAttr), nFirst(0), nCount(0) {}
147 : };
148 :
149 : struct ScLessDefaultAttr
150 : {
151 343 : bool operator() (const ScDefaultAttr& rValue1, const ScDefaultAttr& rValue2) const
152 : {
153 343 : return rValue1.pAttr < rValue2.pAttr;
154 : }
155 : };
156 :
157 : typedef std::set<ScDefaultAttr, ScLessDefaultAttr> ScDefaultAttrSet;
158 :
159 1349 : void ScDocument::MakeTable( SCTAB nTab,bool _bNeedsNameCheck )
160 : {
161 1349 : if ( ValidTab(nTab) && ( nTab >= static_cast<SCTAB>(maTabs.size()) ||!maTabs[nTab]) )
162 : {
163 : // Get Custom prefix
164 752 : const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions();
165 752 : OUString aString = rOpt.GetInitTabPrefix();
166 :
167 752 : aString += OUString::number(nTab+1);
168 752 : if ( _bNeedsNameCheck )
169 752 : CreateValidTabName( aString ); // no doubles
170 752 : if (nTab < static_cast<SCTAB>(maTabs.size()))
171 : {
172 0 : maTabs[nTab] = new ScTable(this, nTab, aString);
173 : }
174 : else
175 : {
176 1504 : while(nTab > static_cast<SCTAB>(maTabs.size()))
177 0 : maTabs.push_back(NULL);
178 752 : maTabs.push_back( new ScTable(this, nTab, aString) );
179 : }
180 752 : maTabs[nTab]->SetLoadingMedium(bLoadingMedium);
181 : }
182 1349 : }
183 :
184 14256 : bool ScDocument::HasTable( SCTAB nTab ) const
185 : {
186 14256 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
187 14256 : if (maTabs[nTab])
188 14256 : return true;
189 :
190 0 : return false;
191 : }
192 :
193 7170 : bool ScDocument::GetName( SCTAB nTab, OUString& rName ) const
194 : {
195 7170 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
196 : {
197 7169 : if (maTabs[nTab])
198 : {
199 7169 : maTabs[nTab]->GetName( rName );
200 7169 : return true;
201 : }
202 : }
203 1 : rName.clear();
204 1 : return false;
205 : }
206 :
207 4 : OUString ScDocument::GetCopyTabName( SCTAB nTab ) const
208 : {
209 4 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabNames.size()))
210 3 : return maTabNames[nTab];
211 1 : return OUString();
212 : }
213 :
214 710 : bool ScDocument::SetCodeName( SCTAB nTab, const OUString& rName )
215 : {
216 710 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
217 : {
218 710 : if (maTabs[nTab])
219 : {
220 710 : maTabs[nTab]->SetCodeName( rName );
221 710 : return true;
222 : }
223 : }
224 : OSL_TRACE( "**** can't set code name %s", OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr() );
225 0 : return false;
226 : }
227 :
228 3893 : bool ScDocument::GetCodeName( SCTAB nTab, OUString& rName ) const
229 : {
230 3893 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
231 3893 : if (maTabs[nTab])
232 : {
233 3893 : maTabs[nTab]->GetCodeName( rName );
234 3893 : return true;
235 : }
236 0 : rName.clear();
237 0 : return false;
238 : }
239 :
240 8223 : bool ScDocument::GetTable( const OUString& rName, SCTAB& rTab ) const
241 : {
242 8223 : OUString aUpperName;
243 8223 : static OUString aCacheName, aCacheUpperName;
244 :
245 8223 : if (aCacheName != rName)
246 : {
247 897 : aCacheName = rName;
248 : // surprisingly slow ...
249 897 : aCacheUpperName = ScGlobal::pCharClass->uppercase(rName);
250 : }
251 8223 : aUpperName = aCacheUpperName;
252 :
253 11609 : for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++)
254 11444 : if (maTabs[i])
255 : {
256 11444 : if (aUpperName.equals(maTabs[i]->GetUpperName()))
257 : {
258 8058 : rTab = i;
259 8058 : return true;
260 : }
261 : }
262 165 : rTab = 0;
263 165 : return false;
264 : }
265 :
266 27099 : std::vector<OUString> ScDocument::GetAllTableNames() const
267 : {
268 27099 : std::vector<OUString> aNames;
269 27099 : aNames.reserve(maTabs.size());
270 27099 : TableContainer::const_iterator it = maTabs.begin(), itEnd = maTabs.end();
271 56525 : for (; it != itEnd; ++it)
272 : {
273 : // Positions need to be preserved for ScCompiler and address convention
274 : // context, so still push an empty string for NULL tabs.
275 29426 : OUString aName;
276 29426 : if (*it)
277 : {
278 29426 : const ScTable& rTab = **it;
279 29426 : rTab.GetName(aName);
280 : }
281 29426 : aNames.push_back(aName);
282 29426 : }
283 :
284 27099 : return aNames;
285 : }
286 :
287 990 : ScDBData* ScDocument::GetAnonymousDBData(SCTAB nTab)
288 : {
289 990 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
290 990 : return maTabs[nTab]->GetAnonymousDBData();
291 0 : return NULL;
292 : }
293 :
294 537010 : SCTAB ScDocument::GetTableCount() const
295 : {
296 537010 : return static_cast<SCTAB>(maTabs.size());
297 : }
298 :
299 44 : void ScDocument::SetAnonymousDBData(SCTAB nTab, ScDBData* pDBData)
300 : {
301 44 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
302 44 : maTabs[nTab]->SetAnonymousDBData(pDBData);
303 44 : }
304 :
305 2897 : bool ScDocument::ValidTabName( const OUString& rName )
306 : {
307 2897 : if (rName.isEmpty())
308 25 : return false;
309 2872 : sal_Int32 nLen = rName.getLength();
310 :
311 : #if 1
312 : // Restrict sheet names to what Excel accepts.
313 : /* TODO: We may want to remove this restriction for full ODFF compliance.
314 : * Merely loading and calculating ODF documents using these characters in
315 : * sheet names is not affected by this, but all sheet name editing and
316 : * copying functionality is, maybe falling back to "Sheet4" or similar. */
317 21128 : for (sal_Int32 i = 0; i < nLen; ++i)
318 : {
319 18256 : const sal_Unicode c = rName[i];
320 18256 : switch (c)
321 : {
322 : case ':':
323 : case '\\':
324 : case '/':
325 : case '?':
326 : case '*':
327 : case '[':
328 : case ']':
329 : // these characters are not allowed to match XL's convention.
330 0 : return false;
331 : case '\'':
332 9 : if (i == 0 || i == nLen - 1)
333 : // single quote is not allowed at the first or last
334 : // character position.
335 0 : return false;
336 9 : break;
337 : }
338 : }
339 : #endif
340 :
341 2872 : return true;
342 : }
343 :
344 1463 : bool ScDocument::ValidNewTabName( const OUString& rName ) const
345 : {
346 1463 : bool bValid = ValidTabName(rName);
347 1463 : TableContainer::const_iterator it = maTabs.begin();
348 2893 : for (; it != maTabs.end() && bValid; ++it)
349 1430 : if ( *it )
350 : {
351 1430 : OUString aOldName;
352 1430 : (*it)->GetName(aOldName);
353 1430 : bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName );
354 : }
355 1463 : return bValid;
356 : }
357 :
358 933 : void ScDocument::CreateValidTabName(OUString& rName) const
359 : {
360 933 : if ( !ValidTabName(rName) )
361 : {
362 : // Find new one
363 :
364 : // Get Custom prefix
365 25 : const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions();
366 25 : OUString aStrTable = rOpt.GetInitTabPrefix();
367 :
368 25 : bool bOk = false;
369 :
370 : // First test if the prefix is valid, if so only avoid doubles
371 25 : bool bPrefix = ValidTabName( aStrTable );
372 : OSL_ENSURE(bPrefix, "Invalid Table Name");
373 : SCTAB nDummy;
374 :
375 50 : for ( SCTAB i = static_cast<SCTAB>(maTabs.size())+1; !bOk ; i++ )
376 : {
377 25 : OUStringBuffer aBuf;
378 25 : aBuf.append(aStrTable);
379 25 : aBuf.append(static_cast<sal_Int32>(i));
380 25 : rName = aBuf.makeStringAndClear();
381 25 : if (bPrefix)
382 25 : bOk = ValidNewTabName( rName );
383 : else
384 0 : bOk = !GetTable( rName, nDummy );
385 50 : }
386 : }
387 : else
388 : {
389 : // testing the supplied Name
390 :
391 908 : if ( !ValidNewTabName(rName) )
392 : {
393 25 : SCTAB i = 1;
394 25 : OUStringBuffer aName;
395 122 : do
396 : {
397 61 : i++;
398 61 : aName = rName;
399 61 : aName.append('_');
400 61 : aName.append(static_cast<sal_Int32>(i));
401 : }
402 183 : while (!ValidNewTabName(aName.toString()) && (i < MAXTAB+1));
403 25 : rName = aName.makeStringAndClear();
404 : }
405 : }
406 933 : }
407 :
408 0 : void ScDocument::CreateValidTabNames(std::vector<OUString>& aNames, SCTAB nCount) const
409 : {
410 0 : aNames.clear();//ensure that the vector is empty
411 :
412 : // Get Custom prefix
413 0 : const ScDefaultsOptions& rOpt = SC_MOD()->GetDefaultsOptions();
414 0 : OUString aStrTable = rOpt.GetInitTabPrefix();
415 :
416 0 : OUStringBuffer rName;
417 0 : bool bOk = false;
418 :
419 : // First test if the prefix is valid, if so only avoid doubles
420 0 : bool bPrefix = ValidTabName( aStrTable );
421 : OSL_ENSURE(bPrefix, "Invalid Table Name");
422 : SCTAB nDummy;
423 0 : SCTAB i = static_cast<SCTAB>(maTabs.size())+1;
424 :
425 0 : for (SCTAB j = 0; j < nCount; ++j)
426 : {
427 0 : bOk = false;
428 0 : while(!bOk)
429 : {
430 0 : rName = aStrTable;
431 0 : rName.append(static_cast<sal_Int32>(i));
432 0 : if (bPrefix)
433 0 : bOk = ValidNewTabName( rName.toString() );
434 : else
435 0 : bOk = !GetTable( rName.toString(), nDummy );
436 0 : i++;
437 : }
438 0 : aNames.push_back(rName.makeStringAndClear());
439 0 : }
440 0 : }
441 :
442 134 : void ScDocument::AppendTabOnLoad(const OUString& rName)
443 : {
444 134 : SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
445 134 : if (!ValidTab(nTabCount))
446 : // max table count reached. No more tables.
447 134 : return;
448 :
449 134 : OUString aName = rName;
450 134 : CreateValidTabName(aName);
451 134 : maTabs.push_back( new ScTable(this, nTabCount, aName) );
452 : }
453 :
454 197 : void ScDocument::SetTabNameOnLoad(SCTAB nTab, const OUString& rName)
455 : {
456 197 : if (!ValidTab(nTab) || static_cast<SCTAB>(maTabs.size()) <= nTab)
457 0 : return;
458 :
459 197 : if (!ValidTabName(rName))
460 0 : return;
461 :
462 197 : maTabs[nTab]->SetName(rName);
463 : }
464 :
465 21 : void ScDocument::InvalidateStreamOnSave()
466 : {
467 21 : TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
468 46 : for (; it != itEnd; ++it)
469 : {
470 25 : ScTable* pTab = *it;
471 25 : if (pTab)
472 25 : pTab->SetStreamValid(false);
473 : }
474 21 : }
475 :
476 462 : bool ScDocument::InsertTab(
477 : SCTAB nPos, const OUString& rName, bool bExternalDocument, bool bUndoDeleteTab )
478 : {
479 462 : SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
480 462 : bool bValid = ValidTab(nTabCount);
481 462 : if ( !bExternalDocument ) // else test rName == "'Doc'!Tab" first
482 462 : bValid = (bValid && ValidNewTabName(rName));
483 462 : if (bValid)
484 : {
485 458 : if (nPos == SC_TAB_APPEND || nPos >= nTabCount)
486 : {
487 397 : nPos = maTabs.size();
488 397 : maTabs.push_back( new ScTable(this, nTabCount, rName) );
489 794 : if ( bExternalDocument )
490 0 : maTabs[nTabCount]->SetVisible( false );
491 : }
492 : else
493 : {
494 61 : if (ValidTab(nPos) && (nPos < nTabCount))
495 : {
496 61 : sc::RefUpdateInsertTabContext aCxt( *this, nPos, 1);
497 :
498 61 : ScRange aRange( 0,0,nPos, MAXCOL,MAXROW,MAXTAB );
499 61 : xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
500 61 : xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,1 );
501 61 : if (pRangeName)
502 40 : pRangeName->UpdateInsertTab(aCxt);
503 : pDBCollection->UpdateReference(
504 61 : URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
505 61 : if (pDPCollection)
506 26 : pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,1 );
507 61 : if (pDetOpList)
508 0 : pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,1 );
509 61 : UpdateChartRef( URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,1 );
510 61 : UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,1 );
511 61 : if ( pUnoBroadcaster )
512 61 : pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,1 ) );
513 :
514 : SCTAB i;
515 61 : TableContainer::iterator it = maTabs.begin();
516 198 : for (; it != maTabs.end(); ++it)
517 137 : if ( *it )
518 137 : (*it)->UpdateInsertTab(aCxt);
519 61 : maTabs.push_back(NULL);
520 187 : for (i = nTabCount; i > nPos; i--)
521 : {
522 126 : maTabs[i] = maTabs[i - 1];
523 : }
524 :
525 61 : maTabs[nPos] = new ScTable(this, nPos, rName);
526 :
527 : // UpdateBroadcastAreas must be called between UpdateInsertTab,
528 : // which ends listening, and StartAllListeners, to not modify
529 : // areas that are to be inserted by starting listeners.
530 61 : UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,1);
531 61 : it = maTabs.begin();
532 259 : for (; it != maTabs.end(); ++it)
533 198 : if ( *it )
534 198 : (*it)->UpdateCompile();
535 :
536 61 : StartAllListeners();
537 :
538 61 : if (pValidationList)
539 0 : pValidationList->UpdateInsertTab(aCxt);
540 :
541 : // sheet names of references are not valid until sheet is inserted
542 61 : if ( pChartListenerCollection )
543 61 : pChartListenerCollection->UpdateScheduledSeriesRanges();
544 :
545 61 : bValid = true;
546 : }
547 : else
548 0 : bValid = false;
549 : }
550 : }
551 :
552 462 : if (bValid)
553 : {
554 458 : sc::SetFormulaDirtyContext aCxt;
555 458 : aCxt.mbClearTabDeletedFlag = bUndoDeleteTab;
556 458 : aCxt.mnTabDeletedStart = nPos;
557 458 : aCxt.mnTabDeletedEnd = nPos;
558 458 : SetAllFormulasDirty(aCxt);
559 : }
560 :
561 462 : return bValid;
562 : }
563 :
564 1 : bool ScDocument::InsertTabs( SCTAB nPos, const std::vector<OUString>& rNames,
565 : bool bExternalDocument, bool bNamesValid )
566 : {
567 1 : SCTAB nNewSheets = static_cast<SCTAB>(rNames.size());
568 1 : SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
569 1 : bool bValid = bNamesValid || ValidTab(nTabCount+nNewSheets);
570 :
571 1 : if (bValid)
572 : {
573 1 : if (nPos == SC_TAB_APPEND || nPos >= nTabCount)
574 : {
575 0 : for ( SCTAB i = 0; i < nNewSheets; ++i )
576 : {
577 0 : maTabs.push_back( new ScTable(this, nTabCount + i, rNames.at(i)) );
578 0 : if ( bExternalDocument )
579 0 : maTabs[nTabCount+i]->SetVisible( false );
580 0 : }
581 : }
582 : else
583 : {
584 1 : if (ValidTab(nPos) && (nPos < nTabCount))
585 : {
586 1 : sc::RefUpdateInsertTabContext aCxt( *this, nPos, nNewSheets);
587 1 : ScRange aRange( 0,0,nPos, MAXCOL,MAXROW,MAXTAB );
588 1 : xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,nNewSheets );
589 1 : xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,nNewSheets );
590 1 : if (pRangeName)
591 0 : pRangeName->UpdateInsertTab(aCxt);
592 : pDBCollection->UpdateReference(
593 1 : URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,nNewSheets );
594 1 : if (pDPCollection)
595 0 : pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,nNewSheets );
596 1 : if (pDetOpList)
597 0 : pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,nNewSheets );
598 1 : UpdateChartRef( URM_INSDEL, 0,0,nPos, MAXCOL,MAXROW,MAXTAB, 0,0,nNewSheets );
599 1 : UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0, nNewSheets );
600 1 : if ( pUnoBroadcaster )
601 1 : pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,nNewSheets ) );
602 :
603 1 : TableContainer::iterator it = maTabs.begin();
604 3 : for (; it != maTabs.end(); ++it)
605 2 : if ( *it )
606 2 : (*it)->UpdateInsertTab(aCxt);
607 1 : it = maTabs.begin();
608 1 : maTabs.insert(it+nPos,nNewSheets, NULL);
609 3 : for (SCTAB i = 0; i < nNewSheets; ++i)
610 : {
611 2 : maTabs[nPos + i] = new ScTable(this, nPos + i, rNames.at(i));
612 : }
613 :
614 : // UpdateBroadcastAreas must be called between UpdateInsertTab,
615 : // which ends listening, and StartAllListeners, to not modify
616 : // areas that are to be inserted by starting listeners.
617 1 : UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,nNewSheets);
618 1 : it = maTabs.begin();
619 5 : for (; it != maTabs.end(); ++it)
620 : {
621 4 : if ( *it )
622 4 : (*it)->UpdateCompile();
623 : }
624 :
625 1 : StartAllListeners();
626 :
627 1 : if (pValidationList)
628 0 : pValidationList->UpdateInsertTab(aCxt);
629 :
630 : // sheet names of references are not valid until sheet is inserted
631 1 : if ( pChartListenerCollection )
632 1 : pChartListenerCollection->UpdateScheduledSeriesRanges();
633 :
634 1 : bValid = true;
635 : }
636 : else
637 0 : bValid = false;
638 : }
639 : }
640 :
641 1 : if (bValid)
642 : {
643 1 : sc::SetFormulaDirtyContext aCxt;
644 1 : SetAllFormulasDirty(aCxt);
645 : }
646 :
647 1 : return bValid;
648 : }
649 :
650 290 : bool ScDocument::DeleteTab( SCTAB nTab )
651 : {
652 290 : bool bValid = false;
653 290 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
654 : {
655 288 : if (maTabs[nTab])
656 : {
657 288 : SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
658 288 : if (nTabCount > 1)
659 : {
660 98 : sc::AutoCalcSwitch aACSwitch(*this, false);
661 196 : sc::RefUpdateDeleteTabContext aCxt( *this, nTab, 1);
662 :
663 98 : ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab );
664 98 : DelBroadcastAreasInRange( aRange );
665 :
666 : // #i8180# remove database ranges etc. that are on the deleted tab
667 : // (restored in undo with ScRefUndoData)
668 :
669 98 : xColNameRanges->DeleteOnTab( nTab );
670 98 : xRowNameRanges->DeleteOnTab( nTab );
671 98 : pDBCollection->DeleteOnTab( nTab );
672 98 : if (pDPCollection)
673 36 : pDPCollection->DeleteOnTab( nTab );
674 98 : if (pDetOpList)
675 0 : pDetOpList->DeleteOnTab( nTab );
676 98 : DeleteAreaLinksOnTab( nTab );
677 :
678 : // normal reference update
679 :
680 98 : aRange.aEnd.SetTab( static_cast<SCTAB>(maTabs.size())-1 );
681 98 : xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 );
682 98 : xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1 );
683 98 : if (pRangeName)
684 33 : pRangeName->UpdateDeleteTab(aCxt);
685 : pDBCollection->UpdateReference(
686 98 : URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
687 98 : if (pDPCollection)
688 36 : pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1 );
689 98 : if (pDetOpList)
690 0 : pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1 );
691 98 : UpdateChartRef( URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1 );
692 98 : UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,-1 );
693 98 : if (pValidationList)
694 0 : pValidationList->UpdateDeleteTab(aCxt);
695 98 : if ( pUnoBroadcaster )
696 98 : pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1 ) );
697 :
698 339 : for (SCTAB i = 0, n = static_cast<SCTAB>(maTabs.size()); i < n; ++i)
699 241 : if (maTabs[i])
700 241 : maTabs[i]->UpdateDeleteTab(aCxt);
701 :
702 98 : TableContainer::iterator it = maTabs.begin() + nTab;
703 98 : delete *it;
704 98 : maTabs.erase(it);
705 : // UpdateBroadcastAreas must be called between UpdateDeleteTab,
706 : // which ends listening, and StartAllListeners, to not modify
707 : // areas that are to be inserted by starting listeners.
708 98 : UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,-1);
709 98 : it = maTabs.begin();
710 241 : for (; it != maTabs.end(); ++it)
711 143 : if ( *it )
712 143 : (*it)->UpdateCompile();
713 : // Excel-Filter deletes some Tables while loading, Listeners will
714 : // only be triggered after the loading is done.
715 98 : if ( !bInsertingFromOtherDoc )
716 : {
717 98 : StartAllListeners();
718 :
719 98 : sc::SetFormulaDirtyContext aFormulaDirtyCxt;
720 98 : SetAllFormulasDirty(aFormulaDirtyCxt);
721 : }
722 : // sheet names of references are not valid until sheet is deleted
723 98 : pChartListenerCollection->UpdateScheduledSeriesRanges();
724 :
725 196 : bValid = true;
726 : }
727 : }
728 : }
729 290 : return bValid;
730 : }
731 :
732 2 : bool ScDocument::DeleteTabs( SCTAB nTab, SCTAB nSheets )
733 : {
734 2 : bool bValid = false;
735 2 : if (ValidTab(nTab) && (nTab + nSheets) < static_cast<SCTAB>(maTabs.size()))
736 : {
737 2 : if (maTabs[nTab])
738 : {
739 2 : SCTAB nTabCount = static_cast<SCTAB>(maTabs.size());
740 2 : if (nTabCount > nSheets)
741 : {
742 2 : sc::AutoCalcSwitch aACSwitch(*this, false);
743 4 : sc::RefUpdateDeleteTabContext aCxt( *this, nTab, nSheets);
744 :
745 7 : for (SCTAB aTab = 0; aTab < nSheets; ++aTab)
746 : {
747 5 : ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTab + aTab );
748 5 : DelBroadcastAreasInRange( aRange );
749 :
750 : // #i8180# remove database ranges etc. that are on the deleted tab
751 : // (restored in undo with ScRefUndoData)
752 :
753 5 : xColNameRanges->DeleteOnTab( nTab + aTab );
754 5 : xRowNameRanges->DeleteOnTab( nTab + aTab );
755 5 : pDBCollection->DeleteOnTab( nTab + aTab );
756 5 : if (pDPCollection)
757 0 : pDPCollection->DeleteOnTab( nTab + aTab );
758 5 : if (pDetOpList)
759 0 : pDetOpList->DeleteOnTab( nTab + aTab );
760 5 : DeleteAreaLinksOnTab( nTab + aTab );
761 : }
762 :
763 2 : if (pRangeName)
764 0 : pRangeName->UpdateDeleteTab(aCxt);
765 :
766 : // normal reference update
767 :
768 2 : ScRange aRange( 0, 0, nTab, MAXCOL, MAXROW, nTabCount - 1 );
769 2 : xColNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1*nSheets );
770 2 : xRowNameRanges->UpdateReference( URM_INSDEL, this, aRange, 0,0,-1*nSheets );
771 : pDBCollection->UpdateReference(
772 2 : URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1*nSheets );
773 2 : if (pDPCollection)
774 0 : pDPCollection->UpdateReference( URM_INSDEL, aRange, 0,0,-1*nSheets );
775 2 : if (pDetOpList)
776 0 : pDetOpList->UpdateReference( this, URM_INSDEL, aRange, 0,0,-1*nSheets );
777 2 : UpdateChartRef( URM_INSDEL, 0,0,nTab, MAXCOL,MAXROW,MAXTAB, 0,0,-1*nSheets );
778 2 : UpdateRefAreaLinks( URM_INSDEL, aRange, 0,0,-1*nSheets );
779 2 : if (pValidationList)
780 0 : pValidationList->UpdateDeleteTab(aCxt);
781 2 : if ( pUnoBroadcaster )
782 2 : pUnoBroadcaster->Broadcast( ScUpdateRefHint( URM_INSDEL, aRange, 0,0,-1*nSheets ) );
783 :
784 10 : for (SCTAB i = 0, n = static_cast<SCTAB>(maTabs.size()); i < n; ++i)
785 8 : if (maTabs[i])
786 8 : maTabs[i]->UpdateDeleteTab(aCxt);
787 :
788 2 : TableContainer::iterator it = maTabs.begin() + nTab;
789 2 : TableContainer::iterator itEnd = it + nSheets;
790 2 : std::for_each(it, itEnd, boost::checked_deleter<ScTable>());
791 2 : maTabs.erase(it, itEnd);
792 : // UpdateBroadcastAreas must be called between UpdateDeleteTab,
793 : // which ends listening, and StartAllListeners, to not modify
794 : // areas that are to be inserted by starting listeners.
795 2 : UpdateBroadcastAreas( URM_INSDEL, aRange, 0,0,-1*nSheets);
796 2 : it = maTabs.begin();
797 5 : for (; it != maTabs.end(); ++it)
798 3 : if ( *it )
799 3 : (*it)->UpdateCompile();
800 : // Excel-Filter deletes some Tables while loading, Listeners will
801 : // only be triggered after the loading is done.
802 2 : if ( !bInsertingFromOtherDoc )
803 : {
804 2 : StartAllListeners();
805 :
806 2 : sc::SetFormulaDirtyContext aFormulaDirtyCxt;
807 2 : SetAllFormulasDirty(aFormulaDirtyCxt);
808 : }
809 : // sheet names of references are not valid until sheet is deleted
810 2 : pChartListenerCollection->UpdateScheduledSeriesRanges();
811 :
812 4 : bValid = true;
813 : }
814 : }
815 : }
816 2 : return bValid;
817 : }
818 :
819 272 : bool ScDocument::RenameTab( SCTAB nTab, const OUString& rName, bool /* bUpdateRef */,
820 : bool bExternalDocument )
821 : {
822 272 : bool bValid = false;
823 : SCTAB i;
824 272 : if (ValidTab(nTab))
825 : {
826 272 : if (maTabs[nTab])
827 : {
828 272 : if ( bExternalDocument )
829 0 : bValid = true; // composed name
830 : else
831 272 : bValid = ValidTabName(rName);
832 971 : for (i=0; (i< static_cast<SCTAB>(maTabs.size())) && bValid; i++)
833 699 : if (maTabs[i] && (i != nTab))
834 : {
835 428 : OUString aOldName;
836 428 : maTabs[i]->GetName(aOldName);
837 428 : bValid = !ScGlobal::GetpTransliteration()->isEqual( rName, aOldName );
838 : }
839 272 : if (bValid)
840 : {
841 : // #i75258# update charts before renaming, so they can get their live data objects.
842 : // Once the charts are live, the sheet can be renamed without problems.
843 271 : if ( pChartListenerCollection )
844 251 : pChartListenerCollection->UpdateChartsContainingTab( nTab );
845 271 : maTabs[nTab]->SetName(rName);
846 :
847 : // If formulas refer to the renamed sheet, the TokenArray remains valid,
848 : // but the XML stream must be re-generated.
849 271 : TableContainer::iterator it = maTabs.begin();
850 969 : for (; it != maTabs.end(); ++it)
851 698 : if ( *it && (*it)->IsStreamValid())
852 0 : (*it)->SetStreamValid( false );
853 : }
854 : }
855 : }
856 272 : return bValid;
857 : }
858 :
859 34 : void ScDocument::SetVisible( SCTAB nTab, bool bVisible )
860 : {
861 34 : if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
862 34 : if (maTabs[nTab])
863 34 : maTabs[nTab]->SetVisible(bVisible);
864 34 : }
865 :
866 7846 : bool ScDocument::IsVisible( SCTAB nTab ) const
867 : {
868 7846 : if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
869 7846 : if (maTabs[nTab])
870 7846 : return maTabs[nTab]->IsVisible();
871 :
872 0 : return false;
873 : }
874 :
875 708950 : bool ScDocument::IsStreamValid( SCTAB nTab ) const
876 : {
877 708950 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
878 708947 : return maTabs[nTab]->IsStreamValid();
879 :
880 3 : return false;
881 : }
882 :
883 2926 : void ScDocument::SetStreamValid( SCTAB nTab, bool bSet, bool bIgnoreLock )
884 : {
885 2926 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
886 2926 : maTabs[nTab]->SetStreamValid( bSet, bIgnoreLock );
887 2926 : }
888 :
889 20876 : void ScDocument::LockStreamValid( bool bLock )
890 : {
891 20876 : mbStreamValidLocked = bLock;
892 20876 : }
893 :
894 10438 : bool ScDocument::IsPendingRowHeights( SCTAB nTab ) const
895 : {
896 10438 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
897 10438 : return maTabs[nTab]->IsPendingRowHeights();
898 :
899 0 : return false;
900 : }
901 :
902 0 : void ScDocument::SetPendingRowHeights( SCTAB nTab, bool bSet )
903 : {
904 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
905 0 : maTabs[nTab]->SetPendingRowHeights( bSet );
906 0 : }
907 :
908 193 : void ScDocument::SetLayoutRTL( SCTAB nTab, bool bRTL )
909 : {
910 193 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
911 : {
912 193 : if ( bImportingXML )
913 : {
914 : // #i57869# only set the LoadingRTL flag, the real setting (including mirroring)
915 : // is applied in SetImportingXML(false). This is so the shapes can be loaded in
916 : // normal LTR mode.
917 :
918 0 : maTabs[nTab]->SetLoadingRTL( bRTL );
919 193 : return;
920 : }
921 :
922 193 : maTabs[nTab]->SetLayoutRTL( bRTL ); // only sets the flag
923 193 : maTabs[nTab]->SetDrawPageSize();
924 :
925 : // mirror existing objects:
926 :
927 193 : if (pDrawLayer)
928 : {
929 4 : SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab));
930 : OSL_ENSURE(pPage,"Page ?");
931 4 : if (pPage)
932 : {
933 4 : SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
934 4 : SdrObject* pObject = aIter.Next();
935 10 : while (pObject)
936 : {
937 : // objects with ScDrawObjData are re-positioned in SetPageSize,
938 : // don't mirror again
939 2 : ScDrawObjData* pData = ScDrawLayer::GetObjData( pObject );
940 2 : if ( !pData )
941 2 : pDrawLayer->MirrorRTL( pObject );
942 :
943 2 : pObject->SetContextWritingMode( bRTL ? WritingMode2::RL_TB : WritingMode2::LR_TB );
944 :
945 2 : pObject = aIter.Next();
946 4 : }
947 : }
948 : }
949 : }
950 : }
951 :
952 154397 : bool ScDocument::IsLayoutRTL( SCTAB nTab ) const
953 : {
954 154397 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab] )
955 154184 : return maTabs[nTab]->IsLayoutRTL();
956 :
957 213 : return false;
958 : }
959 :
960 43430 : bool ScDocument::IsNegativePage( SCTAB nTab ) const
961 : {
962 : // Negative page area is always used for RTL layout.
963 : // The separate method is used to find all RTL handling of drawing objects.
964 43430 : return IsLayoutRTL( nTab );
965 : }
966 :
967 : /* ----------------------------------------------------------------------------
968 : used search area:
969 :
970 : GetCellArea - Only Data
971 : GetTableArea - Data / Attributes
972 : GetPrintArea - intended for character objects,
973 : sweeps attributes all the way to bottom / right
974 : ---------------------------------------------------------------------------- */
975 :
976 31 : bool ScDocument::GetCellArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const
977 : {
978 31 : if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
979 31 : if (maTabs[nTab])
980 31 : return maTabs[nTab]->GetCellArea( rEndCol, rEndRow );
981 :
982 0 : rEndCol = 0;
983 0 : rEndRow = 0;
984 0 : return false;
985 : }
986 :
987 5312 : bool ScDocument::GetTableArea( SCTAB nTab, SCCOL& rEndCol, SCROW& rEndRow ) const
988 : {
989 5312 : if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
990 5312 : if (maTabs[nTab])
991 5312 : return maTabs[nTab]->GetTableArea( rEndCol, rEndRow );
992 :
993 0 : rEndCol = 0;
994 0 : rEndRow = 0;
995 0 : return false;
996 : }
997 :
998 60 : bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow) const
999 : {
1000 60 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB> (maTabs.size()) || !maTabs[nTab])
1001 0 : return false;
1002 :
1003 : SCCOL nCol1, nCol2;
1004 : SCROW nRow1, nRow2;
1005 60 : maTabs[nTab]->GetFirstDataPos(nCol1, nRow1);
1006 60 : maTabs[nTab]->GetLastDataPos(nCol2, nRow2);
1007 :
1008 60 : if (nCol1 > nCol2 || nRow1 > nRow2)
1009 : // invalid range.
1010 1 : return false;
1011 :
1012 : // Make sure the area only shrinks, and doesn't grow.
1013 59 : if (rStartCol < nCol1)
1014 0 : rStartCol = nCol1;
1015 59 : if (nCol2 < rEndCol)
1016 4 : rEndCol = nCol2;
1017 59 : if (rStartRow < nRow1)
1018 0 : rStartRow = nRow1;
1019 59 : if (nRow2 < rEndRow)
1020 8 : rEndRow = nRow2;
1021 :
1022 59 : if (rStartCol > rEndCol || rStartRow > rEndRow)
1023 : // invalid range.
1024 0 : return false;
1025 :
1026 59 : return true; // success!
1027 : }
1028 :
1029 39 : bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStartCol,
1030 : SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly,
1031 : bool bStickyTopRow, bool bStickyLeftCol ) const
1032 : {
1033 39 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB> (maTabs.size()) || !maTabs[nTab])
1034 : {
1035 0 : o_bShrunk = false;
1036 0 : return false;
1037 : }
1038 39 : return maTabs[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow,
1039 78 : bColumnsOnly, bStickyTopRow, bStickyLeftCol);
1040 : }
1041 :
1042 2 : SCROW ScDocument::GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nLastRow ) const
1043 : {
1044 2 : const ScTable* pTab = FetchTable(nTab);
1045 2 : if (!pTab)
1046 0 : return -1;
1047 :
1048 2 : return pTab->GetLastDataRow(nCol1, nCol2, nLastRow);
1049 : }
1050 :
1051 0 : ScAddress ScDocument::GetLastDataPos( SCTAB nTab ) const
1052 : {
1053 0 : const ScTable* pTab = FetchTable(nTab);
1054 0 : if (!pTab)
1055 0 : return ScAddress(ScAddress::INITIALIZE_INVALID);
1056 :
1057 : SCCOL nCol;
1058 : SCROW nRow;
1059 0 : pTab->GetLastDataPos(nCol, nRow);
1060 0 : return ScAddress(nCol, nRow, nTab);
1061 : }
1062 :
1063 : // connected area
1064 :
1065 53 : void ScDocument::GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
1066 : SCCOL& rEndCol, SCROW& rEndRow, bool bIncludeOld, bool bOnlyDown ) const
1067 : {
1068 53 : if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab])
1069 53 : maTabs[nTab]->GetDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bIncludeOld, bOnlyDown );
1070 53 : }
1071 :
1072 0 : void ScDocument::LimitChartArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow,
1073 : SCCOL& rEndCol, SCROW& rEndRow )
1074 : {
1075 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB> (maTabs.size()))
1076 0 : if (maTabs[nTab])
1077 0 : maTabs[nTab]->LimitChartArea( rStartCol, rStartRow, rEndCol, rEndRow );
1078 0 : }
1079 :
1080 0 : void ScDocument::LimitChartIfAll( ScRangeListRef& rRangeList )
1081 : {
1082 0 : ScRangeListRef aNew = new ScRangeList;
1083 0 : if (rRangeList.Is())
1084 : {
1085 0 : for ( size_t i = 0, nCount = rRangeList->size(); i < nCount; i++ )
1086 : {
1087 0 : ScRange aRange( *(*rRangeList)[i] );
1088 0 : if ( ( aRange.aStart.Col() == 0 && aRange.aEnd.Col() == MAXCOL ) ||
1089 0 : ( aRange.aStart.Row() == 0 && aRange.aEnd.Row() == MAXROW ) )
1090 : {
1091 0 : SCCOL nStartCol = aRange.aStart.Col();
1092 0 : SCROW nStartRow = aRange.aStart.Row();
1093 0 : SCCOL nEndCol = aRange.aEnd.Col();
1094 0 : SCROW nEndRow = aRange.aEnd.Row();
1095 0 : SCTAB nTab = aRange.aStart.Tab();
1096 0 : if ( nTab < static_cast<SCTAB> (maTabs.size()) && maTabs[nTab])
1097 0 : maTabs[nTab]->LimitChartArea(nStartCol, nStartRow, nEndCol, nEndRow);
1098 0 : aRange.aStart.SetCol( nStartCol );
1099 0 : aRange.aStart.SetRow( nStartRow );
1100 0 : aRange.aEnd.SetCol( nEndCol );
1101 0 : aRange.aEnd.SetRow( nEndRow );
1102 : }
1103 0 : aNew->Append(aRange);
1104 : }
1105 : }
1106 : else
1107 : {
1108 : OSL_FAIL("LimitChartIfAll: Ref==0");
1109 : }
1110 0 : rRangeList = aNew;
1111 0 : }
1112 :
1113 336 : static void lcl_GetFirstTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark, SCTAB aMaxTab )
1114 : {
1115 : // without ScMarkData, leave start/end unchanged
1116 336 : if ( pTabMark )
1117 : {
1118 96 : for (SCTAB nTab=0; nTab< aMaxTab; ++nTab)
1119 96 : if (pTabMark->GetTableSelect(nTab))
1120 : {
1121 : // find first range of consecutive selected sheets
1122 94 : rTabRangeStart = pTabMark->GetFirstSelected();
1123 188 : while ( nTab+1 < aMaxTab && pTabMark->GetTableSelect(nTab+1) )
1124 0 : ++nTab;
1125 94 : rTabRangeEnd = nTab;
1126 430 : return;
1127 : }
1128 : }
1129 : }
1130 :
1131 336 : static bool lcl_GetNextTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark, SCTAB aMaxTab )
1132 : {
1133 336 : if ( pTabMark )
1134 : {
1135 : // find next range of consecutive selected sheets after rTabRangeEnd
1136 118 : for (SCTAB nTab=rTabRangeEnd+1; nTab< aMaxTab; ++nTab)
1137 24 : if (pTabMark->GetTableSelect(nTab))
1138 : {
1139 0 : rTabRangeStart = nTab;
1140 0 : while ( nTab+1 < aMaxTab && pTabMark->GetTableSelect(nTab+1) )
1141 0 : ++nTab;
1142 0 : rTabRangeEnd = nTab;
1143 0 : return true;
1144 : }
1145 : }
1146 336 : return false;
1147 : }
1148 :
1149 3 : bool ScDocument::CanInsertRow( const ScRange& rRange ) const
1150 : {
1151 3 : SCCOL nStartCol = rRange.aStart.Col();
1152 3 : SCROW nStartRow = rRange.aStart.Row();
1153 3 : SCTAB nStartTab = rRange.aStart.Tab();
1154 3 : SCCOL nEndCol = rRange.aEnd.Col();
1155 3 : SCROW nEndRow = rRange.aEnd.Row();
1156 3 : SCTAB nEndTab = rRange.aEnd.Tab();
1157 3 : PutInOrder( nStartCol, nEndCol );
1158 3 : PutInOrder( nStartRow, nEndRow );
1159 3 : PutInOrder( nStartTab, nEndTab );
1160 3 : SCSIZE nSize = static_cast<SCSIZE>(nEndRow - nStartRow + 1);
1161 :
1162 3 : bool bTest = true;
1163 3 : for (SCTAB i=nStartTab; i<=nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
1164 0 : if (maTabs[i])
1165 0 : bTest &= maTabs[i]->TestInsertRow( nStartCol, nEndCol, nStartRow, nSize );
1166 :
1167 3 : return bTest;
1168 : }
1169 :
1170 : namespace {
1171 :
1172 : struct SetDirtyIfPostponedHandler : std::unary_function<ScTable*, void>
1173 : {
1174 40 : void operator() (ScTable* p)
1175 : {
1176 40 : if (p)
1177 40 : p->SetDirtyIfPostponed();
1178 40 : }
1179 : };
1180 :
1181 : struct BroadcastRecalcOnRefMoveHandler : std::unary_function<ScTable*, void>
1182 : {
1183 184 : void operator() (ScTable* p)
1184 : {
1185 184 : if (p)
1186 184 : p->BroadcastRecalcOnRefMove();
1187 184 : }
1188 : };
1189 :
1190 : }
1191 :
1192 54 : bool ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab,
1193 : SCCOL nEndCol, SCTAB nEndTab,
1194 : SCROW nStartRow, SCSIZE nSize, ScDocument* pRefUndoDoc,
1195 : const ScMarkData* pTabMark )
1196 : {
1197 : SCTAB i;
1198 :
1199 54 : PutInOrder( nStartCol, nEndCol );
1200 54 : PutInOrder( nStartTab, nEndTab );
1201 54 : if ( pTabMark )
1202 : {
1203 11 : nStartTab = 0;
1204 11 : nEndTab = static_cast<SCTAB>(maTabs.size()) -1;
1205 : }
1206 :
1207 54 : bool bTest = true;
1208 54 : bool bRet = false;
1209 54 : bool bOldAutoCalc = GetAutoCalc();
1210 54 : SetAutoCalc( false ); // avoid mulitple calculations
1211 108 : for ( i = nStartTab; i <= nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
1212 54 : if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1213 54 : bTest &= maTabs[i]->TestInsertRow(nStartCol, nEndCol, nStartRow, nSize);
1214 54 : if (bTest)
1215 : {
1216 : // UpdateBroadcastAreas have to be called before UpdateReference, so that entries
1217 : // aren't shifted that would be rebuild at UpdateReference
1218 :
1219 : // handle chunks of consecutive selected sheets together
1220 54 : SCTAB nTabRangeStart = nStartTab;
1221 54 : SCTAB nTabRangeEnd = nEndTab;
1222 54 : lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1223 54 : ScRange aShiftedRange(nStartCol, nStartRow, nTabRangeStart, nEndCol, MAXROW, nTabRangeEnd);
1224 54 : sc::EndListeningContext aEndListenCxt(*this);
1225 :
1226 108 : std::vector<ScAddress> aGroupPos;
1227 54 : do
1228 : {
1229 54 : aShiftedRange.aStart.SetTab(nTabRangeStart);
1230 54 : aShiftedRange.aEnd.SetTab(nTabRangeEnd);
1231 :
1232 : // Collect all formula groups that will get split by the shifting,
1233 : // and end all their listening. Record the position of the top
1234 : // cell of the topmost group, and the position of the bottom cell
1235 : // of the bottommost group.
1236 54 : EndListeningIntersectedGroups(aEndListenCxt, aShiftedRange, &aGroupPos);
1237 :
1238 54 : UpdateBroadcastAreas(URM_INSDEL, aShiftedRange, 0, static_cast<SCsROW>(nSize), 0);
1239 : }
1240 54 : while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1241 :
1242 54 : lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1243 :
1244 108 : sc::RefUpdateContext aCxt(*this);
1245 54 : aCxt.meMode = URM_INSDEL;
1246 54 : aCxt.maRange = aShiftedRange;
1247 54 : aCxt.mnRowDelta = nSize;
1248 54 : do
1249 : {
1250 54 : aCxt.maRange.aStart.SetTab(nTabRangeStart);
1251 54 : aCxt.maRange.aEnd.SetTab(nTabRangeEnd);
1252 54 : UpdateReference(aCxt, pRefUndoDoc, false); // without drawing objects
1253 : }
1254 54 : while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1255 :
1256 : // UpdateReference should have set "needs listening" flags to those
1257 : // whose references have been modified. We also need to set this flag
1258 : // to those that were in the groups that got split by shifting.
1259 54 : SetNeedsListeningGroups(aGroupPos);
1260 :
1261 108 : for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
1262 54 : if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1263 54 : maTabs[i]->InsertRow( nStartCol, nEndCol, nStartRow, nSize );
1264 :
1265 : // UpdateRef for drawing layer must be after inserting,
1266 : // when the new row heights are known.
1267 108 : for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
1268 54 : if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1269 54 : maTabs[i]->UpdateDrawRef( URM_INSDEL,
1270 : nStartCol, nStartRow, nStartTab, nEndCol, MAXROW, nEndTab,
1271 108 : 0, static_cast<SCsROW>(nSize), 0 );
1272 :
1273 54 : if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
1274 : { // A new Listening is needed when references to deleted ranges are restored,
1275 : // previous Listeners were removed in FormulaCell UpdateReference.
1276 0 : StartAllListeners();
1277 : }
1278 : else
1279 : { // Listeners have been removed in UpdateReference
1280 54 : StartNeededListeners();
1281 :
1282 : // At least all cells using range names pointing relative to the
1283 : // moved range must be recalculated, and all cells marked postponed
1284 : // dirty.
1285 54 : TableContainer::iterator it = maTabs.begin();
1286 111 : for (; it != maTabs.end(); ++it)
1287 57 : if (*it)
1288 57 : (*it)->SetDirtyIfPostponed();
1289 :
1290 54 : std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
1291 : }
1292 108 : bRet = true;
1293 : }
1294 54 : SetAutoCalc( bOldAutoCalc );
1295 54 : if ( bRet )
1296 54 : pChartListenerCollection->UpdateDirtyCharts();
1297 54 : return bRet;
1298 : }
1299 :
1300 17 : bool ScDocument::InsertRow( const ScRange& rRange, ScDocument* pRefUndoDoc )
1301 : {
1302 34 : return InsertRow( rRange.aStart.Col(), rRange.aStart.Tab(),
1303 34 : rRange.aEnd.Col(), rRange.aEnd.Tab(),
1304 17 : rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1),
1305 85 : pRefUndoDoc );
1306 : }
1307 :
1308 50 : void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab,
1309 : SCCOL nEndCol, SCTAB nEndTab,
1310 : SCROW nStartRow, SCSIZE nSize,
1311 : ScDocument* pRefUndoDoc, bool* pUndoOutline,
1312 : const ScMarkData* pTabMark )
1313 : {
1314 : SCTAB i;
1315 :
1316 50 : PutInOrder( nStartCol, nEndCol );
1317 50 : PutInOrder( nStartTab, nEndTab );
1318 50 : if ( pTabMark )
1319 : {
1320 17 : nStartTab = 0;
1321 17 : nEndTab = static_cast<SCTAB>(maTabs.size())-1;
1322 : }
1323 :
1324 50 : sc::AutoCalcSwitch aACSwitch(*this, false); // avoid multiple calculations
1325 :
1326 : // handle chunks of consecutive selected sheets together
1327 50 : SCTAB nTabRangeStart = nStartTab;
1328 50 : SCTAB nTabRangeEnd = nEndTab;
1329 50 : lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1330 50 : do
1331 : {
1332 50 : if ( ValidRow(nStartRow+nSize) )
1333 : {
1334 : DelBroadcastAreasInRange( ScRange(
1335 : ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1336 50 : ScAddress( nEndCol, nStartRow+nSize-1, nTabRangeEnd ) ) );
1337 : UpdateBroadcastAreas( URM_INSDEL, ScRange(
1338 : ScAddress( nStartCol, nStartRow+nSize, nTabRangeStart ),
1339 50 : ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, -(static_cast<SCsROW>(nSize)), 0 );
1340 : }
1341 : else
1342 : DelBroadcastAreasInRange( ScRange(
1343 : ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1344 0 : ScAddress( nEndCol, MAXROW, nTabRangeEnd ) ) );
1345 : }
1346 50 : while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1347 :
1348 100 : sc::RefUpdateContext aCxt(*this);
1349 50 : if ( ValidRow(nStartRow+nSize) )
1350 : {
1351 50 : lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1352 50 : aCxt.meMode = URM_INSDEL;
1353 50 : aCxt.maRange = ScRange(nStartCol, nStartRow+nSize, nTabRangeStart, nEndCol, MAXROW, nTabRangeEnd);
1354 50 : aCxt.mnRowDelta = -(static_cast<SCROW>(nSize));
1355 50 : do
1356 : {
1357 50 : UpdateReference(aCxt, pRefUndoDoc, true, false);
1358 : }
1359 50 : while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1360 : }
1361 :
1362 50 : if (pUndoOutline)
1363 3 : *pUndoOutline = false;
1364 :
1365 : // Keep track of the positions of all formula groups that have been joined
1366 : // during row deletion.
1367 100 : std::vector<ScAddress> aGroupPos;
1368 :
1369 104 : for ( i = nStartTab; i <= nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
1370 54 : if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1371 50 : maTabs[i]->DeleteRow(aCxt.maRegroupCols, nStartCol, nEndCol, nStartRow, nSize, pUndoOutline, &aGroupPos);
1372 :
1373 : // Newly joined groups have some of their members still listening. We
1374 : // need to make sure none of them are listening.
1375 50 : EndListeningGroups(aGroupPos);
1376 :
1377 : // Mark all joined groups for group listening.
1378 50 : SetNeedsListeningGroups(aGroupPos);
1379 :
1380 50 : if ( ValidRow(nStartRow+nSize) )
1381 : {
1382 : // Listeners have been removed in UpdateReference
1383 50 : StartNeededListeners();
1384 :
1385 : // At least all cells using range names pointing relative to the moved
1386 : // range must be recalculated, and all cells marked postponed dirty.
1387 50 : TableContainer::iterator it = maTabs.begin();
1388 104 : for (; it != maTabs.end(); ++it)
1389 54 : if (*it)
1390 54 : (*it)->SetDirtyIfPostponed();
1391 :
1392 50 : std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
1393 : }
1394 :
1395 100 : pChartListenerCollection->UpdateDirtyCharts();
1396 50 : }
1397 :
1398 18 : void ScDocument::DeleteRow( const ScRange& rRange, ScDocument* pRefUndoDoc, bool* pUndoOutline )
1399 : {
1400 36 : DeleteRow( rRange.aStart.Col(), rRange.aStart.Tab(),
1401 36 : rRange.aEnd.Col(), rRange.aEnd.Tab(),
1402 18 : rRange.aStart.Row(), static_cast<SCSIZE>(rRange.aEnd.Row()-rRange.aStart.Row()+1),
1403 90 : pRefUndoDoc, pUndoOutline );
1404 18 : }
1405 :
1406 3 : bool ScDocument::CanInsertCol( const ScRange& rRange ) const
1407 : {
1408 3 : SCCOL nStartCol = rRange.aStart.Col();
1409 3 : SCROW nStartRow = rRange.aStart.Row();
1410 3 : SCTAB nStartTab = rRange.aStart.Tab();
1411 3 : SCCOL nEndCol = rRange.aEnd.Col();
1412 3 : SCROW nEndRow = rRange.aEnd.Row();
1413 3 : SCTAB nEndTab = rRange.aEnd.Tab();
1414 3 : PutInOrder( nStartCol, nEndCol );
1415 3 : PutInOrder( nStartRow, nEndRow );
1416 3 : PutInOrder( nStartTab, nEndTab );
1417 3 : SCSIZE nSize = static_cast<SCSIZE>(nEndCol - nStartCol + 1);
1418 :
1419 3 : bool bTest = true;
1420 3 : for (SCTAB i=nStartTab; i<=nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
1421 0 : if (maTabs[i])
1422 0 : bTest &= maTabs[i]->TestInsertCol( nStartRow, nEndRow, nSize );
1423 :
1424 3 : return bTest;
1425 : }
1426 :
1427 37 : bool ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab,
1428 : SCROW nEndRow, SCTAB nEndTab,
1429 : SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc,
1430 : const ScMarkData* pTabMark )
1431 : {
1432 : SCTAB i;
1433 :
1434 37 : PutInOrder( nStartRow, nEndRow );
1435 37 : PutInOrder( nStartTab, nEndTab );
1436 37 : if ( pTabMark )
1437 : {
1438 6 : nStartTab = 0;
1439 6 : nEndTab = static_cast<SCTAB>(maTabs.size())-1;
1440 : }
1441 :
1442 37 : bool bTest = true;
1443 37 : bool bRet = false;
1444 37 : bool bOldAutoCalc = GetAutoCalc();
1445 37 : SetAutoCalc( false ); // avoid multiple calculations
1446 77 : for ( i = nStartTab; i <= nEndTab && bTest && i < static_cast<SCTAB>(maTabs.size()); i++)
1447 40 : if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1448 37 : bTest &= maTabs[i]->TestInsertCol( nStartRow, nEndRow, nSize );
1449 37 : if (bTest)
1450 : {
1451 : // handle chunks of consecutive selected sheets together
1452 37 : SCTAB nTabRangeStart = nStartTab;
1453 37 : SCTAB nTabRangeEnd = nEndTab;
1454 37 : lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1455 37 : do
1456 : {
1457 : UpdateBroadcastAreas( URM_INSDEL, ScRange(
1458 : ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1459 37 : ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), static_cast<SCsCOL>(nSize), 0, 0 );
1460 : }
1461 37 : while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1462 :
1463 37 : lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1464 :
1465 37 : sc::RefUpdateContext aCxt(*this);
1466 37 : aCxt.meMode = URM_INSDEL;
1467 37 : aCxt.maRange = ScRange(nStartCol, nStartRow, nTabRangeStart, MAXCOL, nEndRow, nTabRangeEnd);
1468 37 : aCxt.mnColDelta = nSize;
1469 37 : do
1470 : {
1471 37 : UpdateReference(aCxt, pRefUndoDoc, true, false);
1472 : }
1473 37 : while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1474 :
1475 77 : for (i=nStartTab; i<=nEndTab && i < static_cast<SCTAB>(maTabs.size()); i++)
1476 40 : if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1477 37 : maTabs[i]->InsertCol(aCxt.maRegroupCols, nStartCol, nStartRow, nEndRow, nSize);
1478 :
1479 37 : if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
1480 : { // A new Listening is needed when references to deleted ranges are restored,
1481 : // previous Listeners were removed in FormulaCell UpdateReference.
1482 0 : StartAllListeners();
1483 : }
1484 : else
1485 : {
1486 : // Listeners have been removed in UpdateReference
1487 37 : StartNeededListeners();
1488 : // At least all cells using range names pointing relative to the
1489 : // moved range must be recalculated, and all cells marked postponed
1490 : // dirty.
1491 37 : std::for_each(maTabs.begin(), maTabs.end(), SetDirtyIfPostponedHandler());
1492 : // Cells containing functions such as CELL, COLUMN or ROW may have
1493 : // changed their values on relocation. Broadcast them.
1494 37 : std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
1495 : }
1496 37 : bRet = true;
1497 : }
1498 37 : SetAutoCalc( bOldAutoCalc );
1499 37 : if ( bRet )
1500 37 : pChartListenerCollection->UpdateDirtyCharts();
1501 37 : return bRet;
1502 : }
1503 :
1504 18 : bool ScDocument::InsertCol( const ScRange& rRange, ScDocument* pRefUndoDoc )
1505 : {
1506 18 : return InsertCol( rRange.aStart.Row(), rRange.aStart.Tab(),
1507 18 : rRange.aEnd.Row(), rRange.aEnd.Tab(),
1508 36 : rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1),
1509 72 : pRefUndoDoc );
1510 : }
1511 :
1512 27 : void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab,
1513 : SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc,
1514 : bool* pUndoOutline, const ScMarkData* pTabMark )
1515 : {
1516 : SCTAB i;
1517 :
1518 27 : PutInOrder( nStartRow, nEndRow );
1519 27 : PutInOrder( nStartTab, nEndTab );
1520 27 : if ( pTabMark )
1521 : {
1522 13 : nStartTab = 0;
1523 13 : nEndTab = static_cast<SCTAB>(maTabs.size())-1;
1524 : }
1525 :
1526 27 : sc::AutoCalcSwitch aACSwitch(*this, false); // avoid multiple calculations
1527 :
1528 : // handle chunks of consecutive selected sheets together
1529 27 : SCTAB nTabRangeStart = nStartTab;
1530 27 : SCTAB nTabRangeEnd = nEndTab;
1531 27 : lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1532 27 : do
1533 : {
1534 27 : if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
1535 : {
1536 : DelBroadcastAreasInRange( ScRange(
1537 : ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1538 27 : ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize-1), nEndRow, nTabRangeEnd ) ) );
1539 : UpdateBroadcastAreas( URM_INSDEL, ScRange(
1540 27 : ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart ),
1541 54 : ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), -static_cast<SCsCOL>(nSize), 0, 0 );
1542 : }
1543 : else
1544 : DelBroadcastAreasInRange( ScRange(
1545 : ScAddress( nStartCol, nStartRow, nTabRangeStart ),
1546 0 : ScAddress( MAXCOL, nEndRow, nTabRangeEnd ) ) );
1547 : }
1548 27 : while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1549 :
1550 54 : sc::RefUpdateContext aCxt(*this);
1551 27 : if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
1552 : {
1553 27 : lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) );
1554 27 : aCxt.meMode = URM_INSDEL;
1555 27 : aCxt.maRange = ScRange(sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart, MAXCOL, nEndRow, nTabRangeEnd);
1556 27 : aCxt.mnColDelta = -(static_cast<SCCOL>(nSize));
1557 27 : do
1558 : {
1559 27 : UpdateReference(aCxt, pRefUndoDoc, true, false);
1560 : }
1561 27 : while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark, static_cast<SCTAB>(maTabs.size()) ) );
1562 : }
1563 :
1564 27 : if (pUndoOutline)
1565 3 : *pUndoOutline = false;
1566 :
1567 60 : for (i = nStartTab; i <= nEndTab && i < static_cast<SCTAB>(maTabs.size()); ++i)
1568 : {
1569 33 : if (maTabs[i] && (!pTabMark || pTabMark->GetTableSelect(i)))
1570 27 : maTabs[i]->DeleteCol(aCxt.maRegroupCols, nStartCol, nStartRow, nEndRow, nSize, pUndoOutline);
1571 : }
1572 :
1573 27 : if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) )
1574 : {
1575 : // Listeners have been removed in UpdateReference
1576 27 : StartNeededListeners();
1577 :
1578 : // At least all cells using range names pointing relative to the moved
1579 : // range must be recalculated, and all cells marked postponed dirty.
1580 27 : TableContainer::iterator it = maTabs.begin();
1581 60 : for (; it != maTabs.end(); ++it)
1582 33 : if (*it)
1583 33 : (*it)->SetDirtyIfPostponed();
1584 :
1585 27 : std::for_each(maTabs.begin(), maTabs.end(), BroadcastRecalcOnRefMoveHandler());
1586 : }
1587 :
1588 54 : pChartListenerCollection->UpdateDirtyCharts();
1589 27 : }
1590 :
1591 8 : void ScDocument::DeleteCol( const ScRange& rRange, ScDocument* pRefUndoDoc, bool* pUndoOutline )
1592 : {
1593 8 : DeleteCol( rRange.aStart.Row(), rRange.aStart.Tab(),
1594 8 : rRange.aEnd.Row(), rRange.aEnd.Tab(),
1595 16 : rRange.aStart.Col(), static_cast<SCSIZE>(rRange.aEnd.Col()-rRange.aStart.Col()+1),
1596 32 : pRefUndoDoc, pUndoOutline );
1597 8 : }
1598 :
1599 : // for Area-Links: Insert/delete cells, when the range is changed.
1600 : // (without Paint)
1601 :
1602 4 : static void lcl_GetInsDelRanges( const ScRange& rOld, const ScRange& rNew,
1603 : ScRange& rColRange, bool& rInsCol, bool& rDelCol,
1604 : ScRange& rRowRange, bool& rInsRow, bool& rDelRow )
1605 : {
1606 : OSL_ENSURE( rOld.aStart == rNew.aStart, "FitBlock: Beginning is different" );
1607 :
1608 4 : rInsCol = rDelCol = rInsRow = rDelRow = false;
1609 :
1610 4 : SCCOL nStartX = rOld.aStart.Col();
1611 4 : SCROW nStartY = rOld.aStart.Row();
1612 4 : SCCOL nOldEndX = rOld.aEnd.Col();
1613 4 : SCROW nOldEndY = rOld.aEnd.Row();
1614 4 : SCCOL nNewEndX = rNew.aEnd.Col();
1615 4 : SCROW nNewEndY = rNew.aEnd.Row();
1616 4 : SCTAB nTab = rOld.aStart.Tab();
1617 :
1618 : // if more rows, columns are inserted/deleted at the old height.
1619 4 : bool bGrowY = ( nNewEndY > nOldEndY );
1620 4 : SCROW nColEndY = bGrowY ? nOldEndY : nNewEndY;
1621 4 : SCCOL nRowEndX = bGrowY ? nNewEndX : nOldEndX;
1622 :
1623 : // Columns
1624 :
1625 4 : if ( nNewEndX > nOldEndX ) // Insert columns
1626 : {
1627 3 : rColRange = ScRange( nOldEndX+1, nStartY, nTab, nNewEndX, nColEndY, nTab );
1628 3 : rInsCol = true;
1629 : }
1630 1 : else if ( nNewEndX < nOldEndX ) // Delete columns
1631 : {
1632 0 : rColRange = ScRange( nNewEndX+1, nStartY, nTab, nOldEndX, nColEndY, nTab );
1633 0 : rDelCol = true;
1634 : }
1635 :
1636 : // Rows
1637 :
1638 4 : if ( nNewEndY > nOldEndY ) // Insert rows
1639 : {
1640 3 : rRowRange = ScRange( nStartX, nOldEndY+1, nTab, nRowEndX, nNewEndY, nTab );
1641 3 : rInsRow = true;
1642 : }
1643 1 : else if ( nNewEndY < nOldEndY ) // Delete rows
1644 : {
1645 0 : rRowRange = ScRange( nStartX, nNewEndY+1, nTab, nRowEndX, nOldEndY, nTab );
1646 0 : rDelRow = true;
1647 : }
1648 4 : }
1649 :
1650 6 : bool ScDocument::HasPartOfMerged( const ScRange& rRange )
1651 : {
1652 6 : bool bPart = false;
1653 6 : SCTAB nTab = rRange.aStart.Tab();
1654 :
1655 6 : SCCOL nStartX = rRange.aStart.Col();
1656 6 : SCROW nStartY = rRange.aStart.Row();
1657 6 : SCCOL nEndX = rRange.aEnd.Col();
1658 6 : SCROW nEndY = rRange.aEnd.Row();
1659 :
1660 6 : if (HasAttrib( nStartX, nStartY, nTab, nEndX, nEndY, nTab,
1661 6 : HASATTR_MERGED | HASATTR_OVERLAPPED ))
1662 : {
1663 0 : ExtendMerge( nStartX, nStartY, nEndX, nEndY, nTab );
1664 0 : ExtendOverlapped( nStartX, nStartY, nEndX, nEndY, nTab );
1665 :
1666 0 : bPart = ( nStartX != rRange.aStart.Col() || nEndX != rRange.aEnd.Col() ||
1667 0 : nStartY != rRange.aStart.Row() || nEndY != rRange.aEnd.Row() );
1668 : }
1669 6 : return bPart;
1670 : }
1671 :
1672 38 : size_t ScDocument::GetFormulaHash( const ScAddress& rPos ) const
1673 : {
1674 38 : SCTAB nTab = rPos.Tab();
1675 38 : if (!ValidTab(nTab) || static_cast<size_t>(nTab) >= maTabs.size() || !maTabs[nTab])
1676 0 : return 0;
1677 :
1678 38 : return maTabs[nTab]->GetFormulaHash(rPos.Col(), rPos.Row());
1679 : }
1680 :
1681 6 : ScFormulaVectorState ScDocument::GetFormulaVectorState( const ScAddress& rPos ) const
1682 : {
1683 6 : SCTAB nTab = rPos.Tab();
1684 6 : if (!ValidTab(nTab) || static_cast<size_t>(nTab) >= maTabs.size() || !maTabs[nTab])
1685 0 : return FormulaVectorUnknown;
1686 :
1687 6 : return maTabs[nTab]->GetFormulaVectorState(rPos.Col(), rPos.Row());
1688 : }
1689 :
1690 0 : formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScAddress& rPos )
1691 : {
1692 0 : SCTAB nTab = rPos.Tab();
1693 0 : if (!TableExists(nTab))
1694 0 : return formula::FormulaTokenRef();
1695 :
1696 0 : return maTabs[nTab]->ResolveStaticReference(rPos.Col(), rPos.Row());
1697 : }
1698 :
1699 0 : formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScRange& rRange )
1700 : {
1701 0 : SCTAB nTab = rRange.aStart.Tab();
1702 0 : if (nTab != rRange.aEnd.Tab() || !TableExists(nTab))
1703 0 : return formula::FormulaTokenRef();
1704 :
1705 0 : return maTabs[nTab]->ResolveStaticReference(
1706 0 : rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
1707 : }
1708 :
1709 22 : formula::VectorRefArray ScDocument::FetchVectorRefArray( const ScAddress& rPos, SCROW nLength )
1710 : {
1711 22 : SCTAB nTab = rPos.Tab();
1712 22 : if (!TableExists(nTab))
1713 0 : return formula::VectorRefArray();
1714 :
1715 22 : return maTabs[nTab]->FetchVectorRefArray(rPos.Col(), rPos.Row(), rPos.Row()+nLength-1);
1716 : }
1717 :
1718 4 : bool ScDocument::CanFitBlock( const ScRange& rOld, const ScRange& rNew )
1719 : {
1720 4 : if ( rOld == rNew )
1721 1 : return true;
1722 :
1723 3 : bool bOk = true;
1724 : bool bInsCol,bDelCol,bInsRow,bDelRow;
1725 3 : ScRange aColRange,aRowRange;
1726 3 : lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow );
1727 :
1728 3 : if ( bInsCol && !CanInsertCol( aColRange ) ) // Cells at the edge ?
1729 0 : bOk = false;
1730 3 : if ( bInsRow && !CanInsertRow( aRowRange ) ) // Cells at the edge ?
1731 0 : bOk = false;
1732 :
1733 3 : if ( bInsCol || bDelCol )
1734 : {
1735 3 : aColRange.aEnd.SetCol(MAXCOL);
1736 3 : if ( HasPartOfMerged(aColRange) )
1737 0 : bOk = false;
1738 : }
1739 3 : if ( bInsRow || bDelRow )
1740 : {
1741 3 : aRowRange.aEnd.SetRow(MAXROW);
1742 3 : if ( HasPartOfMerged(aRowRange) )
1743 0 : bOk = false;
1744 : }
1745 :
1746 3 : return bOk;
1747 : }
1748 :
1749 1 : void ScDocument::FitBlock( const ScRange& rOld, const ScRange& rNew, bool bClear )
1750 : {
1751 1 : if (bClear)
1752 1 : DeleteAreaTab( rOld, IDF_ALL );
1753 :
1754 : bool bInsCol,bDelCol,bInsRow,bDelRow;
1755 1 : ScRange aColRange,aRowRange;
1756 1 : lcl_GetInsDelRanges( rOld, rNew, aColRange,bInsCol,bDelCol, aRowRange,bInsRow,bDelRow );
1757 :
1758 1 : if ( bInsCol )
1759 0 : InsertCol( aColRange ); // First insert columns
1760 1 : if ( bInsRow )
1761 0 : InsertRow( aRowRange );
1762 :
1763 1 : if ( bDelRow )
1764 0 : DeleteRow( aRowRange ); // First delete rows
1765 1 : if ( bDelCol )
1766 0 : DeleteCol( aColRange );
1767 :
1768 : // Expand references to inserted rows
1769 :
1770 1 : if ( bInsCol || bInsRow )
1771 : {
1772 0 : ScRange aGrowSource = rOld;
1773 0 : aGrowSource.aEnd.SetCol(std::min( rOld.aEnd.Col(), rNew.aEnd.Col() ));
1774 0 : aGrowSource.aEnd.SetRow(std::min( rOld.aEnd.Row(), rNew.aEnd.Row() ));
1775 0 : SCCOL nGrowX = bInsCol ? ( rNew.aEnd.Col() - rOld.aEnd.Col() ) : 0;
1776 0 : SCROW nGrowY = bInsRow ? ( rNew.aEnd.Row() - rOld.aEnd.Row() ) : 0;
1777 0 : UpdateGrow( aGrowSource, nGrowX, nGrowY );
1778 : }
1779 1 : }
1780 :
1781 217 : void ScDocument::DeleteArea(
1782 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
1783 : InsertDeleteFlags nDelFlag, bool bBroadcast, sc::ColumnSpanSet* pBroadcastSpans )
1784 : {
1785 217 : sc::AutoCalcSwitch aACSwitch(*this, false);
1786 :
1787 217 : PutInOrder( nCol1, nCol2 );
1788 217 : PutInOrder( nRow1, nRow2 );
1789 :
1790 434 : std::vector<ScAddress> aGroupPos;
1791 : // Destroy and reconstruct listeners only if content is affected.
1792 217 : bool bDelContent = ((nDelFlag & ~IDF_CONTENTS) != nDelFlag);
1793 217 : if (bDelContent)
1794 : {
1795 : // Record the positions of top and/or bottom formula groups that intersect
1796 : // the area borders.
1797 200 : sc::EndListeningContext aCxt(*this);
1798 200 : ScRange aRange(nCol1, nRow1, 0, nCol2, nRow2, 0);
1799 470 : for (size_t i = 0; i < maTabs.size(); ++i)
1800 : {
1801 270 : aRange.aStart.SetTab(i);
1802 270 : aRange.aEnd.SetTab(i);
1803 :
1804 270 : EndListeningIntersectedGroups(aCxt, aRange, &aGroupPos);
1805 : }
1806 200 : aCxt.purgeEmptyBroadcasters();
1807 : }
1808 :
1809 520 : for (SCTAB i = 0; i < static_cast<SCTAB>(maTabs.size()); i++)
1810 303 : if (maTabs[i])
1811 303 : if ( rMark.GetTableSelect(i) || bIsUndo )
1812 214 : maTabs[i]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag, bBroadcast, pBroadcastSpans);
1813 :
1814 217 : if (bDelContent)
1815 : {
1816 : // Re-start listeners on those top bottom groups that have been split.
1817 200 : SetNeedsListeningGroups(aGroupPos);
1818 200 : StartNeededListeners();
1819 217 : }
1820 217 : }
1821 :
1822 1045 : void ScDocument::DeleteAreaTab(SCCOL nCol1, SCROW nRow1,
1823 : SCCOL nCol2, SCROW nRow2,
1824 : SCTAB nTab, InsertDeleteFlags nDelFlag)
1825 : {
1826 1045 : PutInOrder( nCol1, nCol2 );
1827 1045 : PutInOrder( nRow1, nRow2 );
1828 1045 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
1829 : {
1830 1041 : bool bOldAutoCalc = GetAutoCalc();
1831 1041 : SetAutoCalc( false ); // avoid multiple calculations
1832 1041 : maTabs[nTab]->DeleteArea(nCol1, nRow1, nCol2, nRow2, nDelFlag);
1833 1041 : SetAutoCalc( bOldAutoCalc );
1834 : }
1835 1045 : }
1836 :
1837 20 : void ScDocument::DeleteAreaTab( const ScRange& rRange, InsertDeleteFlags nDelFlag )
1838 : {
1839 40 : for ( SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); nTab++ )
1840 20 : DeleteAreaTab( rRange.aStart.Col(), rRange.aStart.Row(),
1841 20 : rRange.aEnd.Col(), rRange.aEnd.Row(),
1842 60 : nTab, nDelFlag );
1843 20 : }
1844 :
1845 20 : void ScDocument::InitUndoSelected( ScDocument* pSrcDoc, const ScMarkData& rTabSelection,
1846 : bool bColInfo, bool bRowInfo )
1847 : {
1848 20 : if (bIsUndo)
1849 : {
1850 20 : Clear();
1851 :
1852 20 : SharePooledResources(pSrcDoc);
1853 :
1854 20 : OUString aString;
1855 41 : for (SCTAB nTab = 0; nTab <= rTabSelection.GetLastSelected(); nTab++)
1856 21 : if ( rTabSelection.GetTableSelect( nTab ) )
1857 : {
1858 20 : ScTable* pTable = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
1859 20 : if (nTab < static_cast<SCTAB>(maTabs.size()))
1860 0 : maTabs[nTab] = pTable;
1861 : else
1862 20 : maTabs.push_back(pTable);
1863 : }
1864 : else
1865 : {
1866 1 : if (nTab < static_cast<SCTAB>(maTabs.size()))
1867 0 : maTabs[nTab]=NULL;
1868 : else
1869 1 : maTabs.push_back(NULL);
1870 20 : }
1871 : }
1872 : else
1873 : {
1874 : OSL_FAIL("InitUndo");
1875 : }
1876 20 : }
1877 :
1878 903 : void ScDocument::InitUndo( ScDocument* pSrcDoc, SCTAB nTab1, SCTAB nTab2,
1879 : bool bColInfo, bool bRowInfo )
1880 : {
1881 903 : if (!bIsUndo)
1882 : {
1883 : OSL_FAIL("InitUndo");
1884 903 : return;
1885 : }
1886 :
1887 903 : Clear();
1888 :
1889 : // Undo document shares its pooled resources with the source document.
1890 903 : SharePooledResources(pSrcDoc);
1891 :
1892 903 : if (pSrcDoc->pShell->GetMedium())
1893 903 : maFileURL = pSrcDoc->pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
1894 :
1895 903 : OUString aString;
1896 903 : if ( nTab2 >= static_cast<SCTAB>(maTabs.size()))
1897 903 : maTabs.resize(nTab2 + 1, NULL);
1898 1829 : for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++)
1899 : {
1900 926 : ScTable* pTable = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
1901 926 : maTabs[nTab] = pTable;
1902 903 : }
1903 : }
1904 :
1905 53 : void ScDocument::AddUndoTab( SCTAB nTab1, SCTAB nTab2, bool bColInfo, bool bRowInfo )
1906 : {
1907 53 : if (!bIsUndo)
1908 : {
1909 : OSL_FAIL("AddUndoTab");
1910 53 : return;
1911 : }
1912 :
1913 53 : OUString aString;
1914 53 : if (nTab2 >= static_cast<SCTAB>(maTabs.size()))
1915 : {
1916 22 : maTabs.resize(nTab2+1,NULL);
1917 : }
1918 :
1919 139 : for (SCTAB nTab = nTab1; nTab <= nTab2; nTab++)
1920 86 : if (!maTabs[nTab])
1921 : {
1922 26 : maTabs[nTab] = new ScTable(this, nTab, aString, bColInfo, bRowInfo);
1923 53 : }
1924 : }
1925 :
1926 0 : void ScDocument::SetCutMode( bool bVal )
1927 : {
1928 0 : if (bIsClip)
1929 0 : GetClipParam().mbCutMode = bVal;
1930 : else
1931 : {
1932 : OSL_FAIL("SetCutMode without bIsClip");
1933 : }
1934 0 : }
1935 :
1936 35 : bool ScDocument::IsCutMode()
1937 : {
1938 35 : if (bIsClip)
1939 35 : return GetClipParam().mbCutMode;
1940 : else
1941 : {
1942 : OSL_FAIL("IsCutMode without bIsClip");
1943 0 : return false;
1944 : }
1945 : }
1946 :
1947 361 : void ScDocument::CopyToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1948 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
1949 : InsertDeleteFlags nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
1950 : const ScMarkData* pMarks, bool bColRowFlags )
1951 : {
1952 361 : PutInOrder( nCol1, nCol2 );
1953 361 : PutInOrder( nRow1, nRow2 );
1954 361 : PutInOrder( nTab1, nTab2 );
1955 361 : if( pDestDoc->aDocName.isEmpty() )
1956 295 : pDestDoc->aDocName = aDocName;
1957 361 : if (ValidTab(nTab1) && ValidTab(nTab2))
1958 : {
1959 361 : sc::CopyToDocContext aCxt(*pDestDoc);
1960 361 : bool bOldAutoCalc = pDestDoc->GetAutoCalc();
1961 361 : pDestDoc->SetAutoCalc( false ); // avoid multiple calculations
1962 361 : SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pDestDoc->maTabs.size()));
1963 724 : for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++)
1964 : {
1965 363 : if (maTabs[i] && pDestDoc->maTabs[i])
1966 361 : maTabs[i]->CopyToTable(aCxt, nCol1, nRow1, nCol2, nRow2, nFlags,
1967 361 : bOnlyMarked, pDestDoc->maTabs[i], pMarks,
1968 1083 : false, bColRowFlags );
1969 : }
1970 361 : pDestDoc->SetAutoCalc( bOldAutoCalc );
1971 : }
1972 361 : }
1973 :
1974 0 : void ScDocument::UndoToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1975 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
1976 : InsertDeleteFlags nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
1977 : const ScMarkData* pMarks)
1978 : {
1979 0 : PutInOrder( nCol1, nCol2 );
1980 0 : PutInOrder( nRow1, nRow2 );
1981 0 : PutInOrder( nTab1, nTab2 );
1982 0 : if (ValidTab(nTab1) && ValidTab(nTab2))
1983 : {
1984 0 : sc::AutoCalcSwitch aACSwitch(*pDestDoc, false); // avoid multiple calculations
1985 :
1986 0 : if (nTab1 > 0)
1987 0 : CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, false, pDestDoc, pMarks );
1988 :
1989 0 : sc::CopyToDocContext aCxt(*pDestDoc);
1990 : OSL_ASSERT( nTab2 < static_cast<SCTAB>(maTabs.size()) && nTab2 < static_cast<SCTAB>(pDestDoc->maTabs.size()));
1991 0 : for (SCTAB i = nTab1; i <= nTab2; i++)
1992 : {
1993 0 : if (maTabs[i] && pDestDoc->maTabs[i])
1994 0 : maTabs[i]->UndoToTable(aCxt, nCol1, nRow1, nCol2, nRow2, nFlags,
1995 0 : bOnlyMarked, pDestDoc->maTabs[i], pMarks);
1996 : }
1997 :
1998 0 : if (nTab2 < MAXTAB)
1999 0 : CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA, false, pDestDoc, pMarks );
2000 : }
2001 0 : }
2002 :
2003 710 : void ScDocument::CopyToDocument(const ScRange& rRange,
2004 : InsertDeleteFlags nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
2005 : const ScMarkData* pMarks, bool bColRowFlags)
2006 : {
2007 710 : ScRange aNewRange = rRange;
2008 710 : aNewRange.Justify();
2009 :
2010 710 : if( pDestDoc->aDocName.isEmpty() )
2011 710 : pDestDoc->aDocName = aDocName;
2012 :
2013 710 : sc::AutoCalcSwitch aACSwitch(*pDestDoc, false); // avoid multiple calculations
2014 :
2015 1420 : sc::CopyToDocContext aCxt(*pDestDoc);
2016 710 : aCxt.setStartListening(false);
2017 :
2018 710 : SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pDestDoc->maTabs.size()));
2019 1416 : for (SCTAB i = aNewRange.aStart.Tab(); i <= aNewRange.aEnd.Tab() && i < nMinSizeBothTabs; i++)
2020 : {
2021 706 : ScTable* pTab = FetchTable(i);
2022 706 : ScTable* pDestTab = pDestDoc->FetchTable(i);
2023 706 : if (!pTab || !pDestTab)
2024 1 : continue;
2025 :
2026 : pTab->CopyToTable(
2027 1410 : aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(), aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
2028 2115 : nFlags, bOnlyMarked, pDestTab, pMarks, false, bColRowFlags);
2029 : }
2030 :
2031 1420 : pDestDoc->StartAllListeners(aNewRange);
2032 710 : }
2033 :
2034 8 : void ScDocument::UndoToDocument(const ScRange& rRange,
2035 : InsertDeleteFlags nFlags, bool bOnlyMarked, ScDocument* pDestDoc,
2036 : const ScMarkData* pMarks)
2037 : {
2038 8 : sc::AutoCalcSwitch aAutoCalcSwitch(*this, false);
2039 :
2040 8 : ScRange aNewRange = rRange;
2041 8 : aNewRange.Justify();
2042 8 : SCTAB nTab1 = aNewRange.aStart.Tab();
2043 8 : SCTAB nTab2 = aNewRange.aEnd.Tab();
2044 :
2045 16 : sc::CopyToDocContext aCxt(*pDestDoc);
2046 8 : if (nTab1 > 0)
2047 2 : CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTab1-1, IDF_FORMULA, false, pDestDoc, pMarks );
2048 :
2049 8 : SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pDestDoc->maTabs.size()));
2050 16 : for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++)
2051 : {
2052 8 : if (maTabs[i] && pDestDoc->maTabs[i])
2053 16 : maTabs[i]->UndoToTable(aCxt, aNewRange.aStart.Col(), aNewRange.aStart.Row(),
2054 8 : aNewRange.aEnd.Col(), aNewRange.aEnd.Row(),
2055 32 : nFlags, bOnlyMarked, pDestDoc->maTabs[i], pMarks);
2056 : }
2057 :
2058 8 : if (nTab2 < static_cast<SCTAB>(maTabs.size()))
2059 16 : CopyToDocument( 0,0,nTab2+1, MAXCOL,MAXROW,maTabs.size(), IDF_FORMULA, false, pDestDoc, pMarks );
2060 8 : }
2061 :
2062 : // bUseRangeForVBA added for VBA api support to allow content of a specified
2063 : // range to be copied ( e.g. don't use marked data but the just the range
2064 : // specified by rClipParam
2065 55 : void ScDocument::CopyToClip(const ScClipParam& rClipParam,
2066 : ScDocument* pClipDoc, const ScMarkData* pMarks,
2067 : bool bAllTabs, bool bKeepScenarioFlags, bool bIncludeObjects, bool bCloneNoteCaptions, bool bUseRangeForVBA )
2068 : {
2069 : OSL_ENSURE( !bUseRangeForVBA && ( bAllTabs || pMarks ), "CopyToClip: ScMarkData fails" );
2070 :
2071 55 : if (bIsClip)
2072 55 : return;
2073 :
2074 55 : if (!pClipDoc)
2075 : {
2076 : OSL_TRACE("CopyToClip: no ClipDoc");
2077 0 : pClipDoc = ScModule::GetClipDoc();
2078 : }
2079 :
2080 55 : if (pShell->GetMedium())
2081 : {
2082 55 : pClipDoc->maFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
2083 : // for unsaved files use the title name and adjust during save of file
2084 55 : if (pClipDoc->maFileURL.isEmpty())
2085 36 : pClipDoc->maFileURL = pShell->GetName();
2086 : }
2087 : else
2088 : {
2089 0 : pClipDoc->maFileURL = pShell->GetName();
2090 : }
2091 :
2092 : //init maTabNames
2093 152 : for (TableContainer::iterator itr = maTabs.begin(); itr != maTabs.end(); ++itr)
2094 : {
2095 97 : if( *itr )
2096 : {
2097 97 : OUString aTabName;
2098 97 : (*itr)->GetName(aTabName);
2099 97 : pClipDoc->maTabNames.push_back(aTabName);
2100 : }
2101 : else
2102 0 : pClipDoc->maTabNames.push_back(OUString());
2103 : }
2104 :
2105 55 : pClipDoc->aDocName = aDocName;
2106 55 : pClipDoc->SetClipParam(rClipParam);
2107 55 : ScRange aClipRange = rClipParam.getWholeRange();
2108 55 : SCTAB nTab = aClipRange.aStart.Tab();
2109 55 : SCTAB i = 0;
2110 55 : SCTAB nEndTab = static_cast<SCTAB>(maTabs.size());
2111 :
2112 55 : if ( bUseRangeForVBA )
2113 : {
2114 0 : pClipDoc->ResetClip( this, nTab );
2115 0 : i = nTab;
2116 0 : nEndTab = nTab + 1;
2117 : }
2118 : else
2119 55 : pClipDoc->ResetClip(this, pMarks);
2120 :
2121 55 : sc::CopyToClipContext aCxt(*pClipDoc, bKeepScenarioFlags, bCloneNoteCaptions);
2122 55 : CopyRangeNamesToClip(pClipDoc, aClipRange, pMarks, bAllTabs);
2123 :
2124 152 : for ( ; i < nEndTab; ++i)
2125 : {
2126 97 : if (!maTabs[i] || i >= static_cast<SCTAB>(pClipDoc->maTabs.size()) || !pClipDoc->maTabs[i])
2127 43 : continue;
2128 :
2129 54 : if ( !bUseRangeForVBA && ( pMarks && !pMarks->GetTableSelect(i) ) )
2130 0 : continue;
2131 :
2132 54 : maTabs[i]->CopyToClip(aCxt, rClipParam.maRanges, pClipDoc->maTabs[i]);
2133 :
2134 54 : if (pDrawLayer && bIncludeObjects)
2135 : {
2136 : // also copy drawing objects
2137 : Rectangle aObjRect = GetMMRect(
2138 14 : aClipRange.aStart.Col(), aClipRange.aStart.Row(), aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i);
2139 14 : pDrawLayer->CopyToClip(pClipDoc, i, aObjRect);
2140 : }
2141 : }
2142 :
2143 : // Make sure to mark overlapped cells.
2144 55 : pClipDoc->ExtendMerge(aClipRange, true);
2145 : }
2146 :
2147 4 : void ScDocument::CopyStaticToDocument(const ScRange& rSrcRange, SCTAB nDestTab, ScDocument* pDestDoc)
2148 : {
2149 4 : if (!pDestDoc)
2150 0 : return;
2151 :
2152 4 : ScTable* pSrcTab = rSrcRange.aStart.Tab() < static_cast<SCTAB>(maTabs.size()) ? maTabs[rSrcRange.aStart.Tab()] : NULL;
2153 4 : ScTable* pDestTab = nDestTab < static_cast<SCTAB>(pDestDoc->maTabs.size()) ? pDestDoc->maTabs[nDestTab] : NULL;
2154 :
2155 4 : if (!pSrcTab || !pDestTab)
2156 0 : return;
2157 :
2158 4 : pDestDoc->GetFormatTable()->MergeFormatter(*GetFormatTable());
2159 4 : SvNumberFormatterMergeMap aMap = pDestDoc->GetFormatTable()->ConvertMergeTableToMap();
2160 :
2161 : pSrcTab->CopyStaticToDocument(
2162 8 : rSrcRange.aStart.Col(), rSrcRange.aStart.Row(), rSrcRange.aEnd.Col(), rSrcRange.aEnd.Row(),
2163 12 : aMap, pDestTab);
2164 : }
2165 :
2166 1 : void ScDocument::CopyCellToDocument( const ScAddress& rSrcPos, const ScAddress& rDestPos, ScDocument& rDestDoc )
2167 : {
2168 1 : if (!TableExists(rSrcPos.Tab()) || !rDestDoc.TableExists(rDestPos.Tab()))
2169 1 : return;
2170 :
2171 1 : ScTable& rSrcTab = *maTabs[rSrcPos.Tab()];
2172 1 : ScTable& rDestTab = *rDestDoc.maTabs[rDestPos.Tab()];
2173 :
2174 1 : rSrcTab.CopyCellToDocument(rSrcPos.Col(), rSrcPos.Row(), rDestPos.Col(), rDestPos.Row(), rDestTab);
2175 : }
2176 :
2177 0 : void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
2178 : SCCOL nCol2, SCROW nRow2,
2179 : SCTAB nTab, ScDocument* pClipDoc)
2180 : {
2181 0 : if (!bIsClip)
2182 : {
2183 0 : if (!pClipDoc)
2184 : {
2185 : OSL_TRACE("CopyTabToClip: no ClipDoc");
2186 0 : pClipDoc = ScModule::GetClipDoc();
2187 : }
2188 :
2189 0 : if (pShell->GetMedium())
2190 : {
2191 0 : pClipDoc->maFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
2192 : // for unsaved files use the title name and adjust during save of file
2193 0 : if (pClipDoc->maFileURL.isEmpty())
2194 0 : pClipDoc->maFileURL = pShell->GetName();
2195 : }
2196 : else
2197 : {
2198 0 : pClipDoc->maFileURL = pShell->GetName();
2199 : }
2200 :
2201 : //init maTabNames
2202 0 : for (TableContainer::iterator itr = maTabs.begin(); itr != maTabs.end(); ++itr)
2203 : {
2204 0 : if( *itr )
2205 : {
2206 0 : OUString aTabName;
2207 0 : (*itr)->GetName(aTabName);
2208 0 : pClipDoc->maTabNames.push_back(aTabName);
2209 : }
2210 : else
2211 0 : pClipDoc->maTabNames.push_back(OUString());
2212 : }
2213 :
2214 0 : PutInOrder( nCol1, nCol2 );
2215 0 : PutInOrder( nRow1, nRow2 );
2216 :
2217 0 : ScClipParam& rClipParam = pClipDoc->GetClipParam();
2218 0 : pClipDoc->aDocName = aDocName;
2219 0 : rClipParam.maRanges.RemoveAll();
2220 0 : rClipParam.maRanges.Append(ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0));
2221 0 : pClipDoc->ResetClip( this, nTab );
2222 :
2223 0 : sc::CopyToClipContext aCxt(*pClipDoc, false, true);
2224 0 : if (nTab < static_cast<SCTAB>(maTabs.size()) && nTab < static_cast<SCTAB>(pClipDoc->maTabs.size()))
2225 0 : if (maTabs[nTab] && pClipDoc->maTabs[nTab])
2226 0 : maTabs[nTab]->CopyToClip(aCxt, nCol1, nRow1, nCol2, nRow2, pClipDoc->maTabs[nTab]);
2227 :
2228 0 : pClipDoc->GetClipParam().mbCutMode = false;
2229 : }
2230 0 : }
2231 :
2232 1 : void ScDocument::TransposeClip( ScDocument* pTransClip, InsertDeleteFlags nFlags, bool bAsLink )
2233 : {
2234 : OSL_ENSURE( bIsClip && pTransClip && pTransClip->bIsClip,
2235 : "TransposeClip with wrong Document" );
2236 :
2237 : // initialize
2238 : // -> pTransClip has to be delted before the original document!
2239 :
2240 1 : pTransClip->ResetClip(this, nullptr); // all
2241 :
2242 : // Take over range
2243 :
2244 1 : if (pRangeName)
2245 : {
2246 0 : pTransClip->GetRangeName()->clear();
2247 0 : ScRangeName::const_iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
2248 0 : for (; itr != itrEnd; ++itr)
2249 : {
2250 0 : sal_uInt16 nIndex = itr->second->GetIndex();
2251 0 : ScRangeData* pData = new ScRangeData(*itr->second);
2252 0 : if (pTransClip->pRangeName->insert(pData))
2253 0 : pData->SetIndex(nIndex);
2254 : }
2255 : }
2256 :
2257 : // The data
2258 :
2259 1 : ScRange aClipRange = GetClipParam().getWholeRange();
2260 1 : if ( ValidRow(aClipRange.aEnd.Row()-aClipRange.aStart.Row()) )
2261 : {
2262 2 : for (SCTAB i=0; i< static_cast<SCTAB>(maTabs.size()); i++)
2263 1 : if (maTabs[i])
2264 : {
2265 : OSL_ENSURE( pTransClip->maTabs[i], "TransposeClip: Table not there" );
2266 2 : maTabs[i]->TransposeClip( aClipRange.aStart.Col(), aClipRange.aStart.Row(),
2267 1 : aClipRange.aEnd.Col(), aClipRange.aEnd.Row(),
2268 4 : pTransClip->maTabs[i], nFlags, bAsLink );
2269 :
2270 1 : if ( pDrawLayer && ( nFlags & IDF_OBJECTS ) )
2271 : {
2272 : // Drawing objects are copied to the new area without transposing.
2273 : // CopyFromClip is used to adjust the objects to the transposed block's
2274 : // cell range area.
2275 : // (pDrawLayer in the original clipboard document is set only if there
2276 : // are drawing objects to copy)
2277 :
2278 0 : pTransClip->InitDrawLayer();
2279 0 : Rectangle aSourceRect = GetMMRect( aClipRange.aStart.Col(), aClipRange.aStart.Row(),
2280 0 : aClipRange.aEnd.Col(), aClipRange.aEnd.Row(), i );
2281 : Rectangle aDestRect = pTransClip->GetMMRect( 0, 0,
2282 0 : static_cast<SCCOL>(aClipRange.aEnd.Row() - aClipRange.aStart.Row()),
2283 0 : static_cast<SCROW>(aClipRange.aEnd.Col() - aClipRange.aStart.Col()), i );
2284 0 : pTransClip->pDrawLayer->CopyFromClip( pDrawLayer, i, aSourceRect, ScAddress(0,0,i), aDestRect );
2285 : }
2286 : }
2287 :
2288 1 : pTransClip->SetClipParam(GetClipParam());
2289 1 : pTransClip->GetClipParam().transpose();
2290 : }
2291 : else
2292 : {
2293 : OSL_TRACE("TransposeClip: Too big");
2294 : }
2295 :
2296 : // This happens only when inserting...
2297 :
2298 1 : GetClipParam().mbCutMode = false;
2299 1 : }
2300 :
2301 : namespace {
2302 :
2303 6 : void copyUsedNamesToClip(ScRangeName* pClipRangeName, ScRangeName* pRangeName, const std::set<sal_uInt16>& rUsedNames)
2304 : {
2305 6 : pClipRangeName->clear();
2306 6 : ScRangeName::const_iterator itr = pRangeName->begin(), itrEnd = pRangeName->end();
2307 13 : for (; itr != itrEnd; ++itr) //TODO: also DB and Pivot regions!!!
2308 : {
2309 7 : sal_uInt16 nIndex = itr->second->GetIndex();
2310 7 : bool bInUse = (rUsedNames.count(nIndex) > 0);
2311 7 : if (!bInUse)
2312 6 : continue;
2313 :
2314 1 : ScRangeData* pData = new ScRangeData(*itr->second);
2315 1 : if (pClipRangeName->insert(pData))
2316 1 : pData->SetIndex(nIndex);
2317 : }
2318 6 : }
2319 :
2320 : }
2321 :
2322 55 : void ScDocument::CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs)
2323 : {
2324 55 : if (!pRangeName || pRangeName->empty())
2325 104 : return;
2326 :
2327 6 : std::set<sal_uInt16> aUsedNames; // indexes of named ranges that are used in the copied cells
2328 6 : SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pClipDoc->maTabs.size()));
2329 12 : for (SCTAB i = 0; i < nMinSizeBothTabs; ++i)
2330 6 : if (maTabs[i] && pClipDoc->maTabs[i])
2331 6 : if ( bAllTabs || !pMarks || pMarks->GetTableSelect(i) )
2332 6 : maTabs[i]->FindRangeNamesInUse(
2333 6 : rClipRange.aStart.Col(), rClipRange.aStart.Row(),
2334 18 : rClipRange.aEnd.Col(), rClipRange.aEnd.Row(), aUsedNames);
2335 :
2336 6 : copyUsedNamesToClip(pClipDoc->GetRangeName(), pRangeName, aUsedNames);
2337 : }
2338 :
2339 91 : ScDocument::NumFmtMergeHandler::NumFmtMergeHandler(ScDocument* pDoc, ScDocument* pSrcDoc) :
2340 91 : mpDoc(pDoc)
2341 : {
2342 91 : mpDoc->MergeNumberFormatter(pSrcDoc);
2343 91 : }
2344 :
2345 91 : ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
2346 : {
2347 91 : mpDoc->pFormatExchangeList = NULL;
2348 91 : }
2349 :
2350 42759 : void ScDocument::ClearFormulaContext()
2351 : {
2352 42759 : mpFormulaGroupCxt.reset();
2353 42759 : }
2354 :
2355 73118 : SvtBroadcaster* ScDocument::GetBroadcaster( const ScAddress& rPos )
2356 : {
2357 73118 : ScTable* pTab = FetchTable(rPos.Tab());
2358 73118 : if (!pTab)
2359 0 : return NULL;
2360 :
2361 73118 : return pTab->GetBroadcaster(rPos.Col(), rPos.Row());
2362 : }
2363 :
2364 14 : const SvtBroadcaster* ScDocument::GetBroadcaster( const ScAddress& rPos ) const
2365 : {
2366 14 : const ScTable* pTab = FetchTable(rPos.Tab());
2367 14 : if (!pTab)
2368 0 : return NULL;
2369 :
2370 14 : return pTab->GetBroadcaster(rPos.Col(), rPos.Row());
2371 : }
2372 :
2373 125 : void ScDocument::DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, const ScAddress& rTopPos, SCROW nLength )
2374 : {
2375 125 : ScTable* pTab = FetchTable(rTopPos.Tab());
2376 125 : if (!pTab || nLength <= 0)
2377 125 : return;
2378 :
2379 125 : pTab->DeleteBroadcasters(rBlockPos, rTopPos.Col(), rTopPos.Row(), rTopPos.Row()+nLength-1);
2380 : }
2381 :
2382 0 : bool ScDocument::HasBroadcaster( SCTAB nTab, SCCOL nCol ) const
2383 : {
2384 0 : const ScTable* pTab = FetchTable(nTab);
2385 0 : if (!pTab)
2386 0 : return false;
2387 :
2388 0 : return pTab->HasBroadcaster(nCol);
2389 : }
2390 :
2391 : #if DEBUG_COLUMN_STORAGE
2392 : void ScDocument::DumpFormulaGroups( SCTAB nTab, SCCOL nCol ) const
2393 : {
2394 : const ScTable* pTab = FetchTable(nTab);
2395 : if (!pTab)
2396 : return;
2397 :
2398 : pTab->DumpFormulaGroups(nCol);
2399 : }
2400 : #endif
2401 :
2402 : #if DEBUG_AREA_BROADCASTER
2403 : void ScDocument::DumpAreaBroadcasters() const
2404 : {
2405 : if (pBASM)
2406 : pBASM->Dump();
2407 : }
2408 : #endif
2409 :
2410 21341767 : bool ScDocument::TableExists( SCTAB nTab ) const
2411 : {
2412 21341767 : return ValidTab(nTab) && static_cast<size_t>(nTab) < maTabs.size() && maTabs[nTab];
2413 : }
2414 :
2415 289614 : ScTable* ScDocument::FetchTable( SCTAB nTab )
2416 : {
2417 289614 : if (!TableExists(nTab))
2418 232 : return NULL;
2419 :
2420 289382 : return maTabs[nTab];
2421 : }
2422 :
2423 20482048 : const ScTable* ScDocument::FetchTable( SCTAB nTab ) const
2424 : {
2425 20482048 : if (!TableExists(nTab))
2426 20477952 : return NULL;
2427 :
2428 4096 : return maTabs[nTab];
2429 : }
2430 :
2431 91 : void ScDocument::MergeNumberFormatter(ScDocument* pSrcDoc)
2432 : {
2433 91 : SvNumberFormatter* pThisFormatter = xPoolHelper->GetFormTable();
2434 91 : SvNumberFormatter* pOtherFormatter = pSrcDoc->xPoolHelper->GetFormTable();
2435 91 : if (pOtherFormatter && pOtherFormatter != pThisFormatter)
2436 : {
2437 : SvNumberFormatterIndexTable* pExchangeList =
2438 19 : pThisFormatter->MergeFormatter(*(pOtherFormatter));
2439 19 : if (!pExchangeList->empty())
2440 5 : pFormatExchangeList = pExchangeList;
2441 : }
2442 91 : }
2443 :
2444 771 : ScClipParam& ScDocument::GetClipParam()
2445 : {
2446 771 : if (!mpClipParam.get())
2447 19 : mpClipParam.reset(new ScClipParam);
2448 :
2449 771 : return *mpClipParam;
2450 : }
2451 :
2452 68 : void ScDocument::SetClipParam(const ScClipParam& rParam)
2453 : {
2454 68 : mpClipParam.reset(new ScClipParam(rParam));
2455 68 : }
2456 :
2457 1318 : bool ScDocument::IsClipboardSource() const
2458 : {
2459 1318 : ScDocument* pClipDoc = ScModule::GetClipDoc();
2460 1318 : return pClipDoc && pClipDoc->xPoolHelper.is() &&
2461 1318 : xPoolHelper->GetDocPool() == pClipDoc->xPoolHelper->GetDocPool();
2462 : }
2463 :
2464 78 : void ScDocument::StartListeningFromClip( SCCOL nCol1, SCROW nRow1,
2465 : SCCOL nCol2, SCROW nRow2,
2466 : const ScMarkData& rMark, InsertDeleteFlags nInsFlag )
2467 : {
2468 78 : if (nInsFlag & IDF_CONTENTS)
2469 : {
2470 : boost::shared_ptr<sc::ColumnBlockPositionSet> pSet(
2471 61 : new sc::ColumnBlockPositionSet(*this));
2472 :
2473 122 : sc::StartListeningContext aStartCxt(*this, pSet);
2474 122 : sc::EndListeningContext aEndCxt(*this, pSet, NULL);
2475 :
2476 61 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
2477 61 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
2478 119 : for (; itr != itrEnd && *itr < nMax; ++itr)
2479 58 : if (maTabs[*itr])
2480 119 : maTabs[*itr]->StartListeningFormulaCells(aStartCxt, aEndCxt, nCol1, nRow1, nCol2, nRow2);
2481 : }
2482 78 : }
2483 :
2484 78 : void ScDocument::SetDirtyFromClip(
2485 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, const ScMarkData& rMark,
2486 : InsertDeleteFlags nInsFlag, sc::ColumnSpanSet& rBroadcastSpans )
2487 : {
2488 78 : if (nInsFlag & IDF_CONTENTS)
2489 : {
2490 61 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
2491 61 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
2492 119 : for (; itr != itrEnd && *itr < nMax; ++itr)
2493 58 : if (maTabs[*itr])
2494 58 : maTabs[*itr]->SetDirtyFromClip(nCol1, nRow1, nCol2, nRow2, rBroadcastSpans);
2495 : }
2496 78 : }
2497 :
2498 196865 : bool ScDocument::InitColumnBlockPosition( sc::ColumnBlockPosition& rBlockPos, SCTAB nTab, SCCOL nCol )
2499 : {
2500 196865 : if (!TableExists(nTab))
2501 0 : return false;
2502 :
2503 196865 : return maTabs[nTab]->InitColumnBlockPosition(rBlockPos, nCol);
2504 : }
2505 :
2506 70 : void ScDocument::CopyBlockFromClip(
2507 : sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
2508 : const ScMarkData& rMark, SCsCOL nDx, SCsROW nDy )
2509 : {
2510 70 : TableContainer& rClipTabs = rCxt.getClipDoc()->maTabs;
2511 70 : SCTAB nTabEnd = rCxt.getTabEnd();
2512 70 : SCTAB nClipTab = 0;
2513 137 : for (SCTAB i = rCxt.getTabStart(); i <= nTabEnd && i < static_cast<SCTAB>(maTabs.size()); i++)
2514 : {
2515 67 : if (maTabs[i] && rMark.GetTableSelect(i) )
2516 : {
2517 67 : while (!rClipTabs[nClipTab]) nClipTab = (nClipTab+1) % (static_cast<SCTAB>(rClipTabs.size()));
2518 :
2519 67 : maTabs[i]->CopyFromClip(
2520 134 : rCxt, nCol1, nRow1, nCol2, nRow2, nDx, nDy, rClipTabs[nClipTab]);
2521 :
2522 67 : if (rCxt.getClipDoc()->pDrawLayer && (rCxt.getInsertFlag() & IDF_OBJECTS))
2523 : {
2524 : // also copy drawing objects
2525 :
2526 : // drawing layer must be created before calling CopyFromClip
2527 : // (ScDocShell::MakeDrawLayer also does InitItems etc.)
2528 : OSL_ENSURE( pDrawLayer, "CopyBlockFromClip: No drawing layer" );
2529 1 : if ( pDrawLayer )
2530 : {
2531 : // For GetMMRect, the row heights in the target document must already be valid
2532 : // (copied in an extra step before pasting, or updated after pasting cells, but
2533 : // before pasting objects).
2534 :
2535 : Rectangle aSourceRect = rCxt.getClipDoc()->GetMMRect(
2536 0 : nCol1-nDx, nRow1-nDy, nCol2-nDx, nRow2-nDy, nClipTab );
2537 0 : Rectangle aDestRect = GetMMRect( nCol1, nRow1, nCol2, nRow2, i );
2538 0 : pDrawLayer->CopyFromClip(rCxt.getClipDoc()->pDrawLayer, nClipTab, aSourceRect,
2539 0 : ScAddress( nCol1, nRow1, i ), aDestRect );
2540 : }
2541 : }
2542 :
2543 67 : nClipTab = (nClipTab+1) % (static_cast<SCTAB>(rClipTabs.size()));
2544 : }
2545 : }
2546 70 : if (rCxt.getInsertFlag() & IDF_CONTENTS)
2547 : {
2548 53 : nClipTab = 0;
2549 103 : for (SCTAB i = rCxt.getTabStart(); i <= nTabEnd && i < static_cast<SCTAB>(maTabs.size()); i++)
2550 : {
2551 50 : if (maTabs[i] && rMark.GetTableSelect(i) )
2552 : {
2553 50 : while (!rClipTabs[nClipTab]) nClipTab = (nClipTab+1) % (static_cast<SCTAB>(rClipTabs.size()));
2554 50 : SCsTAB nDz = ((SCsTAB)i) - nClipTab;
2555 :
2556 : // ranges of consecutive selected tables (in clipboard and dest. doc)
2557 : // must be handled in one UpdateReference call
2558 50 : SCTAB nFollow = 0;
2559 150 : while ( i + nFollow < nTabEnd
2560 0 : && rMark.GetTableSelect( i + nFollow + 1 )
2561 0 : && nClipTab + nFollow < MAXTAB
2562 50 : && rClipTabs[(nClipTab + nFollow + 1) % static_cast<SCTAB>(rClipTabs.size())] )
2563 0 : ++nFollow;
2564 :
2565 50 : sc::RefUpdateContext aRefCxt(*this);
2566 50 : aRefCxt.maRange = ScRange(nCol1, nRow1, i, nCol2, nRow2, i+nFollow);
2567 50 : aRefCxt.mnColDelta = nDx;
2568 50 : aRefCxt.mnRowDelta = nDy;
2569 50 : aRefCxt.mnTabDelta = nDz;
2570 50 : if (rCxt.getClipDoc()->GetClipParam().mbCutMode)
2571 : {
2572 : // Update references only if cut originates from the same
2573 : // document we are pasting into.
2574 16 : if (rCxt.getClipDoc()->GetPool() == GetPool())
2575 : {
2576 16 : bool bOldInserting = IsInsertingFromOtherDoc();
2577 16 : SetInsertingFromOtherDoc( true);
2578 16 : aRefCxt.meMode = URM_MOVE;
2579 16 : UpdateReference(aRefCxt, rCxt.getUndoDoc(), false);
2580 16 : SetInsertingFromOtherDoc( bOldInserting);
2581 : }
2582 : }
2583 : else
2584 : {
2585 34 : aRefCxt.meMode = URM_COPY;
2586 34 : UpdateReference(aRefCxt, rCxt.getUndoDoc(), false);
2587 : }
2588 :
2589 50 : nClipTab = (nClipTab+nFollow+1) % (static_cast<SCTAB>(rClipTabs.size()));
2590 50 : i = sal::static_int_cast<SCTAB>( i + nFollow );
2591 : }
2592 : }
2593 : }
2594 70 : }
2595 :
2596 38 : void ScDocument::CopyNonFilteredFromClip(
2597 : sc::CopyFromClipContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
2598 : const ScMarkData& rMark, SCsCOL nDx, SCROW & rClipStartRow )
2599 : {
2600 : // call CopyBlockFromClip for ranges of consecutive non-filtered rows
2601 : // nCol1/nRow1 etc. is in target doc
2602 :
2603 : // filtered state is taken from first used table in clipboard (as in GetClipArea)
2604 38 : SCTAB nFlagTab = 0;
2605 38 : TableContainer& rClipTabs = rCxt.getClipDoc()->maTabs;
2606 76 : while ( nFlagTab < static_cast<SCTAB>(rClipTabs.size()) && !rClipTabs[nFlagTab] )
2607 0 : ++nFlagTab;
2608 :
2609 38 : SCROW nSourceRow = rClipStartRow;
2610 38 : SCROW nSourceEnd = 0;
2611 38 : if (!rCxt.getClipDoc()->GetClipParam().maRanges.empty())
2612 38 : nSourceEnd = rCxt.getClipDoc()->GetClipParam().maRanges.front()->aEnd.Row();
2613 38 : SCROW nDestRow = nRow1;
2614 :
2615 114 : while ( nSourceRow <= nSourceEnd && nDestRow <= nRow2 )
2616 : {
2617 : // skip filtered rows
2618 38 : nSourceRow = rCxt.getClipDoc()->FirstNonFilteredRow(nSourceRow, nSourceEnd, nFlagTab);
2619 :
2620 38 : if ( nSourceRow <= nSourceEnd )
2621 : {
2622 : // look for more non-filtered rows following
2623 38 : SCROW nLastRow = nSourceRow;
2624 38 : rCxt.getClipDoc()->RowFiltered(nSourceRow, nFlagTab, NULL, &nLastRow);
2625 38 : SCROW nFollow = nLastRow - nSourceRow;
2626 :
2627 38 : if (nFollow > nSourceEnd - nSourceRow)
2628 38 : nFollow = nSourceEnd - nSourceRow;
2629 38 : if (nFollow > nRow2 - nDestRow)
2630 0 : nFollow = nRow2 - nDestRow;
2631 :
2632 38 : SCsROW nNewDy = ((SCsROW)nDestRow) - nSourceRow;
2633 : CopyBlockFromClip(
2634 38 : rCxt, nCol1, nDestRow, nCol2, nDestRow + nFollow, rMark, nDx, nNewDy);
2635 :
2636 38 : nSourceRow += nFollow + 1;
2637 38 : nDestRow += nFollow + 1;
2638 : }
2639 : }
2640 38 : rClipStartRow = nSourceRow;
2641 38 : }
2642 :
2643 : namespace {
2644 :
2645 77 : class BroadcastAction : public sc::ColumnSpanSet::ColumnAction
2646 : {
2647 : ScDocument& mrDoc;
2648 : ScColumn* mpCol;
2649 :
2650 : public:
2651 77 : BroadcastAction( ScDocument& rDoc ) : mrDoc(rDoc), mpCol(NULL) {}
2652 :
2653 112 : virtual void startColumn( ScColumn* pCol ) SAL_OVERRIDE
2654 : {
2655 112 : mpCol = pCol;
2656 112 : }
2657 :
2658 250 : virtual void execute( SCROW nRow1, SCROW nRow2, bool bVal ) SAL_OVERRIDE
2659 : {
2660 250 : if (!bVal)
2661 387 : return;
2662 :
2663 : assert(mpCol);
2664 113 : ScRange aRange(mpCol->GetCol(), nRow1, mpCol->GetTab());
2665 113 : aRange.aEnd.SetRow(nRow2);
2666 113 : mrDoc.BroadcastCells(aRange, SC_HINT_DATACHANGED);
2667 : };
2668 : };
2669 :
2670 : }
2671 :
2672 78 : void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMark,
2673 : InsertDeleteFlags nInsFlag,
2674 : ScDocument* pRefUndoDoc, ScDocument* pClipDoc, bool bResetCut,
2675 : bool bAsLink, bool bIncludeFiltered, bool bSkipAttrForEmpty,
2676 : const ScRangeList * pDestRanges )
2677 : {
2678 78 : if (bIsClip)
2679 1 : return;
2680 :
2681 78 : if (!pClipDoc)
2682 : {
2683 : OSL_FAIL("CopyFromClip: no ClipDoc");
2684 0 : pClipDoc = ScModule::GetClipDoc();
2685 : }
2686 :
2687 78 : if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
2688 1 : return;
2689 :
2690 77 : sc::AutoCalcSwitch aACSwitch(*this, false); // temporarily turn off auto calc.
2691 :
2692 154 : NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
2693 :
2694 77 : SCCOL nAllCol1 = rDestRange.aStart.Col();
2695 77 : SCROW nAllRow1 = rDestRange.aStart.Row();
2696 77 : SCCOL nAllCol2 = rDestRange.aEnd.Col();
2697 77 : SCROW nAllRow2 = rDestRange.aEnd.Row();
2698 :
2699 77 : SCCOL nXw = 0;
2700 77 : SCROW nYw = 0;
2701 77 : ScRange aClipRange = pClipDoc->GetClipParam().getWholeRange();
2702 154 : for (SCTAB nTab = 0; nTab < static_cast<SCTAB>(pClipDoc->maTabs.size()); nTab++) // find largest merge overlap
2703 77 : if (pClipDoc->maTabs[nTab]) // all sheets of the clipboard content
2704 : {
2705 77 : SCCOL nThisEndX = aClipRange.aEnd.Col();
2706 77 : SCROW nThisEndY = aClipRange.aEnd.Row();
2707 77 : pClipDoc->ExtendMerge( aClipRange.aStart.Col(),
2708 : aClipRange.aStart.Row(),
2709 154 : nThisEndX, nThisEndY, nTab );
2710 : // only extra value from ExtendMerge
2711 77 : nThisEndX = sal::static_int_cast<SCCOL>( nThisEndX - aClipRange.aEnd.Col() );
2712 77 : nThisEndY = sal::static_int_cast<SCROW>( nThisEndY - aClipRange.aEnd.Row() );
2713 77 : if ( nThisEndX > nXw )
2714 0 : nXw = nThisEndX;
2715 77 : if ( nThisEndY > nYw )
2716 0 : nYw = nThisEndY;
2717 : }
2718 :
2719 : SCCOL nDestAddX;
2720 : SCROW nDestAddY;
2721 77 : pClipDoc->GetClipArea( nDestAddX, nDestAddY, bIncludeFiltered );
2722 77 : nXw = sal::static_int_cast<SCCOL>( nXw + nDestAddX );
2723 77 : nYw = sal::static_int_cast<SCROW>( nYw + nDestAddY ); // ClipArea, plus ExtendMerge value
2724 :
2725 : /* Decide which contents to delete before copying. Delete all
2726 : contents if nInsFlag contains any real content flag.
2727 : #i102056# Notes are pasted from clipboard in a second pass,
2728 : together with the special flag IDF_ADDNOTES that states to not
2729 : overwrite/delete existing cells but to insert the notes into
2730 : these cells. In this case, just delete old notes from the
2731 : destination area. */
2732 77 : InsertDeleteFlags nDelFlag = IDF_NONE;
2733 77 : if ( (nInsFlag & (IDF_CONTENTS | IDF_ADDNOTES)) == (IDF_NOTE | IDF_ADDNOTES) )
2734 0 : nDelFlag |= IDF_NOTE;
2735 77 : else if ( nInsFlag & IDF_CONTENTS )
2736 60 : nDelFlag |= IDF_CONTENTS;
2737 :
2738 77 : if (nInsFlag & IDF_ATTRIB)
2739 56 : nDelFlag |= IDF_ATTRIB;
2740 :
2741 154 : sc::CopyFromClipContext aCxt(*this, pRefUndoDoc, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty);
2742 77 : std::pair<SCTAB,SCTAB> aTabRanges = getMarkedTableRange(maTabs, rMark);
2743 77 : aCxt.setTabRange(aTabRanges.first, aTabRanges.second);
2744 77 : aCxt.setDeleteFlag(nDelFlag);
2745 :
2746 154 : ScRangeList aLocalRangeList;
2747 77 : if (!pDestRanges)
2748 : {
2749 77 : aLocalRangeList.Append( rDestRange);
2750 77 : pDestRanges = &aLocalRangeList;
2751 : }
2752 :
2753 77 : bInsertingFromOtherDoc = true; // No Broadcast/Listener created at Insert
2754 :
2755 154 : sc::ColumnSpanSet aBroadcastSpans(false);
2756 :
2757 77 : SCCOL nClipStartCol = aClipRange.aStart.Col();
2758 77 : SCROW nClipStartRow = aClipRange.aStart.Row();
2759 77 : SCROW nClipEndRow = aClipRange.aEnd.Row();
2760 154 : for ( size_t nRange = 0; nRange < pDestRanges->size(); ++nRange )
2761 : {
2762 77 : const ScRange* pRange = (*pDestRanges)[nRange];
2763 77 : SCCOL nCol1 = pRange->aStart.Col();
2764 77 : SCROW nRow1 = pRange->aStart.Row();
2765 77 : SCCOL nCol2 = pRange->aEnd.Col();
2766 77 : SCROW nRow2 = pRange->aEnd.Row();
2767 :
2768 77 : if (bSkipAttrForEmpty)
2769 : {
2770 : // Delete cells in the destination only if their corresponding clip cells are not empty.
2771 2 : aCxt.setDestRange(nCol1, nRow1, nCol2, nRow2);
2772 2 : DeleteBeforeCopyFromClip(aCxt, rMark, aBroadcastSpans);
2773 : }
2774 : else
2775 75 : DeleteArea(nCol1, nRow1, nCol2, nRow2, rMark, nDelFlag, false, &aBroadcastSpans);
2776 :
2777 77 : if (CopyOneCellFromClip(aCxt, nCol1, nRow1, nCol2, nRow2))
2778 12 : continue;
2779 :
2780 65 : SCCOL nC1 = nCol1;
2781 65 : SCROW nR1 = nRow1;
2782 65 : SCCOL nC2 = nC1 + nXw;
2783 65 : if (nC2 > nCol2)
2784 0 : nC2 = nCol2;
2785 65 : SCROW nR2 = nR1 + nYw;
2786 65 : if (nR2 > nRow2)
2787 0 : nR2 = nRow2;
2788 :
2789 65 : const SCCOLROW nThreshold = 8192;
2790 65 : bool bPreallocatePattern = ((nInsFlag & IDF_ATTRIB) && (nRow2 - nRow1 > nThreshold));
2791 65 : std::vector< SCTAB > vTables;
2792 :
2793 65 : if (bPreallocatePattern)
2794 : {
2795 0 : for (SCTAB i = aCxt.getTabStart(); i <= aCxt.getTabEnd(); ++i)
2796 0 : if (maTabs[i] && rMark.GetTableSelect( i ) )
2797 0 : vTables.push_back( i );
2798 : }
2799 :
2800 67 : do
2801 : {
2802 : // Pasting is done column-wise, when pasting to a filtered
2803 : // area this results in partitioning and we have to
2804 : // remember and reset the start row for each column until
2805 : // it can be advanced for the next chunk of unfiltered
2806 : // rows.
2807 67 : SCROW nSaveClipStartRow = nClipStartRow;
2808 67 : do
2809 : {
2810 67 : nClipStartRow = nSaveClipStartRow;
2811 67 : SCsCOL nDx = ((SCsCOL)nC1) - nClipStartCol;
2812 67 : SCsROW nDy = ((SCsROW)nR1) - nClipStartRow;
2813 67 : if ( bIncludeFiltered )
2814 : {
2815 : CopyBlockFromClip(
2816 29 : aCxt, nC1, nR1, nC2, nR2, rMark, nDx, nDy);
2817 29 : nClipStartRow += nR2 - nR1 + 1;
2818 : }
2819 : else
2820 : {
2821 : CopyNonFilteredFromClip(
2822 38 : aCxt, nC1, nR1, nC2, nR2, rMark, nDx, nClipStartRow);
2823 : }
2824 67 : nC1 = nC2 + 1;
2825 67 : nC2 = std::min((SCCOL)(nC1 + nXw), nCol2);
2826 67 : } while (nC1 <= nCol2);
2827 67 : if (nClipStartRow > nClipEndRow)
2828 66 : nClipStartRow = aClipRange.aStart.Row();
2829 67 : nC1 = nCol1;
2830 67 : nC2 = nC1 + nXw;
2831 67 : if (nC2 > nCol2)
2832 0 : nC2 = nCol2;
2833 :
2834 : // Preallocate pattern memory once if further chunks are to be pasted.
2835 67 : if (bPreallocatePattern && (nR2+1) <= nRow2)
2836 : {
2837 0 : SCROW nR3 = nR2 + 1;
2838 0 : for (size_t j = 0; j < vTables.size(); ++j)
2839 : {
2840 0 : SCTAB nTab = vTables[j];
2841 0 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
2842 : {
2843 : // Pattern count of the first chunk pasted.
2844 0 : SCSIZE nChunk = GetPatternCount( nTab, nCol, nR1, nR2);
2845 : // If it is only one pattern per chunk and chunks are
2846 : // pasted consecutively then it will get its range
2847 : // enlarged for each chunk and no further allocation
2848 : // happens. For non-consecutive chunks we're out of
2849 : // luck in this case.
2850 0 : if (nChunk > 1)
2851 : {
2852 0 : SCSIZE nNeeded = nChunk * (nRow2 - nR3 + 1) / (nYw + 1);
2853 0 : SCSIZE nRemain = GetPatternCount( nTab, nCol, nR3, nRow2);
2854 0 : if (nNeeded > nRemain)
2855 : {
2856 0 : SCSIZE nCurr = GetPatternCount( nTab, nCol);
2857 0 : ReservePatternCount( nTab, nCol, nCurr + nNeeded);
2858 : }
2859 : }
2860 : }
2861 : }
2862 0 : bPreallocatePattern = false;
2863 : }
2864 :
2865 67 : nR1 = nR2 + 1;
2866 67 : nR2 = std::min((SCROW)(nR1 + nYw), nRow2);
2867 67 : } while (nR1 <= nRow2);
2868 65 : }
2869 :
2870 77 : bInsertingFromOtherDoc = false;
2871 :
2872 : // Create Listener after everything has been inserted
2873 77 : StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
2874 :
2875 : {
2876 77 : ScBulkBroadcast aBulkBroadcast( GetBASM());
2877 :
2878 : // Set all formula cells dirty, and collect non-empty non-formula cell
2879 : // positions so that we can broadcast on them below.
2880 77 : SetDirtyFromClip(nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag, aBroadcastSpans);
2881 :
2882 154 : BroadcastAction aAction(*this);
2883 154 : aBroadcastSpans.executeColumnAction(*this, aAction);
2884 : }
2885 :
2886 77 : if (bResetCut)
2887 150 : pClipDoc->GetClipParam().mbCutMode = false;
2888 : }
2889 :
2890 1 : void ScDocument::CopyMultiRangeFromClip(
2891 : const ScAddress& rDestPos, const ScMarkData& rMark, InsertDeleteFlags nInsFlag, ScDocument* pClipDoc,
2892 : bool bResetCut, bool bAsLink, bool /*bIncludeFiltered*/, bool bSkipAttrForEmpty)
2893 : {
2894 1 : if (bIsClip)
2895 0 : return;
2896 :
2897 1 : if (!pClipDoc->bIsClip || !pClipDoc->GetTableCount())
2898 : // There is nothing in the clip doc to copy.
2899 0 : return;
2900 :
2901 : // Right now, we don't allow pasting into filtered rows, so we don't even handle it here.
2902 :
2903 1 : sc::AutoCalcSwitch aACSwitch(*this, false); // turn of auto calc temporarily.
2904 2 : NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
2905 :
2906 1 : ScRange aDestRange;
2907 1 : rMark.GetMarkArea(aDestRange);
2908 :
2909 1 : bInsertingFromOtherDoc = true; // No Broadcast/Listener created at Insert
2910 :
2911 1 : SCCOL nCol1 = rDestPos.Col();
2912 1 : SCROW nRow1 = rDestPos.Row();
2913 1 : ScClipParam& rClipParam = pClipDoc->GetClipParam();
2914 :
2915 2 : sc::ColumnSpanSet aBroadcastSpans(false);
2916 :
2917 1 : if (!bSkipAttrForEmpty)
2918 : {
2919 : // Do the deletion first.
2920 1 : InsertDeleteFlags nDelFlag = IDF_CONTENTS;
2921 1 : SCCOL nColSize = rClipParam.getPasteColSize();
2922 1 : SCROW nRowSize = rClipParam.getPasteRowSize();
2923 :
2924 1 : DeleteArea(nCol1, nRow1, nCol1+nColSize-1, nRow1+nRowSize-1, rMark, nDelFlag, false, &aBroadcastSpans);
2925 : }
2926 :
2927 2 : sc::CopyFromClipContext aCxt(*this, NULL, pClipDoc, nInsFlag, bAsLink, bSkipAttrForEmpty);
2928 1 : std::pair<SCTAB,SCTAB> aTabRanges = getMarkedTableRange(maTabs, rMark);
2929 1 : aCxt.setTabRange(aTabRanges.first, aTabRanges.second);
2930 :
2931 4 : for (size_t i = 0, n = rClipParam.maRanges.size(); i < n; ++i)
2932 : {
2933 3 : ScRange* p = rClipParam.maRanges[i];
2934 :
2935 3 : SCROW nRowCount = p->aEnd.Row() - p->aStart.Row() + 1;
2936 3 : SCsCOL nDx = static_cast<SCsCOL>(nCol1 - p->aStart.Col());
2937 3 : SCsROW nDy = static_cast<SCsROW>(nRow1 - p->aStart.Row());
2938 3 : SCCOL nCol2 = nCol1 + p->aEnd.Col() - p->aStart.Col();
2939 3 : SCROW nEndRow = nRow1 + nRowCount - 1;
2940 :
2941 3 : CopyBlockFromClip(aCxt, nCol1, nRow1, nCol2, nEndRow, rMark, nDx, nDy);
2942 :
2943 3 : switch (rClipParam.meDirection)
2944 : {
2945 : case ScClipParam::Row:
2946 : // Begin row for the next range being pasted.
2947 3 : nRow1 += nRowCount;
2948 3 : break;
2949 : case ScClipParam::Column:
2950 0 : nCol1 += p->aEnd.Col() - p->aStart.Col() + 1;
2951 0 : break;
2952 : default:
2953 : ;
2954 : }
2955 : }
2956 :
2957 1 : bInsertingFromOtherDoc = false;
2958 :
2959 : // Create Listener after everything has been inserted
2960 1 : StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
2961 2 : aDestRange.aEnd.Col(), aDestRange.aEnd.Row(), rMark, nInsFlag );
2962 : // Re-broadcast after all Listener have been created
2963 : SetDirtyFromClip(
2964 2 : aDestRange.aStart.Col(), aDestRange.aStart.Row(), aDestRange.aEnd.Col(), aDestRange.aEnd.Row(),
2965 3 : rMark, nInsFlag, aBroadcastSpans);
2966 :
2967 1 : if (bResetCut)
2968 2 : pClipDoc->GetClipParam().mbCutMode = false;
2969 : }
2970 :
2971 16 : void ScDocument::SetClipArea( const ScRange& rArea, bool bCut )
2972 : {
2973 16 : if (bIsClip)
2974 : {
2975 16 : ScClipParam& rClipParam = GetClipParam();
2976 16 : rClipParam.maRanges.RemoveAll();
2977 16 : rClipParam.maRanges.Append(rArea);
2978 16 : rClipParam.mbCutMode = bCut;
2979 : }
2980 : else
2981 : {
2982 : OSL_FAIL("SetClipArea: No Clip");
2983 : }
2984 16 : }
2985 :
2986 137 : void ScDocument::GetClipArea(SCCOL& nClipX, SCROW& nClipY, bool bIncludeFiltered)
2987 : {
2988 137 : if (!bIsClip)
2989 : {
2990 : OSL_FAIL("GetClipArea: No Clip");
2991 0 : return;
2992 : }
2993 :
2994 137 : ScRangeList& rClipRanges = GetClipParam().maRanges;
2995 137 : if (rClipRanges.empty())
2996 : // No clip range. Bail out.
2997 0 : return;
2998 :
2999 137 : ScRange* p = rClipRanges.front();
3000 137 : SCCOL nStartCol = p->aStart.Col();
3001 137 : SCCOL nEndCol = p->aEnd.Col();
3002 137 : SCROW nStartRow = p->aStart.Row();
3003 137 : SCROW nEndRow = p->aEnd.Row();
3004 137 : for ( size_t i = 1, n = rClipRanges.size(); i < n; ++i )
3005 : {
3006 0 : p = rClipRanges[ i ];
3007 0 : if (p->aStart.Col() < nStartCol)
3008 0 : nStartCol = p->aStart.Col();
3009 0 : if (p->aStart.Row() < nStartRow)
3010 0 : nStartRow = p->aStart.Row();
3011 0 : if (p->aEnd.Col() > nEndCol)
3012 0 : nEndCol = p->aEnd.Col();
3013 0 : if (p->aEnd.Row() < nEndRow)
3014 0 : nEndRow = p->aEnd.Row();
3015 : }
3016 :
3017 137 : nClipX = nEndCol - nStartCol;
3018 :
3019 137 : if ( bIncludeFiltered )
3020 66 : nClipY = nEndRow - nStartRow;
3021 : else
3022 : {
3023 : // count non-filtered rows
3024 : // count on first used table in clipboard
3025 71 : SCTAB nCountTab = 0;
3026 142 : while ( nCountTab < static_cast<SCTAB>(maTabs.size()) && !maTabs[nCountTab] )
3027 0 : ++nCountTab;
3028 :
3029 71 : SCROW nResult = CountNonFilteredRows(nStartRow, nEndRow, nCountTab);
3030 :
3031 71 : if ( nResult > 0 )
3032 71 : nClipY = nResult - 1;
3033 : else
3034 0 : nClipY = 0; // always return at least 1 row
3035 : }
3036 : }
3037 :
3038 28 : void ScDocument::GetClipStart(SCCOL& nClipX, SCROW& nClipY)
3039 : {
3040 28 : if (bIsClip)
3041 : {
3042 28 : ScRangeList& rClipRanges = GetClipParam().maRanges;
3043 28 : if ( !rClipRanges.empty() )
3044 : {
3045 28 : nClipX = rClipRanges.front()->aStart.Col();
3046 28 : nClipY = rClipRanges.front()->aStart.Row();
3047 : }
3048 : }
3049 : else
3050 : {
3051 : OSL_FAIL("GetClipStart: No Clip");
3052 : }
3053 28 : }
3054 :
3055 21 : bool ScDocument::HasClipFilteredRows()
3056 : {
3057 : // count on first used table in clipboard
3058 21 : SCTAB nCountTab = 0;
3059 42 : while ( nCountTab < static_cast<SCTAB>(maTabs.size()) && !maTabs[nCountTab] )
3060 0 : ++nCountTab;
3061 :
3062 21 : ScRangeList& rClipRanges = GetClipParam().maRanges;
3063 21 : if ( rClipRanges.empty() )
3064 0 : return false;
3065 :
3066 42 : for ( size_t i = 0, n = rClipRanges.size(); i < n; ++i )
3067 : {
3068 21 : ScRange* p = rClipRanges[ i ];
3069 21 : bool bAnswer = maTabs[nCountTab]->HasFilteredRows(p->aStart.Row(), p->aEnd.Row());
3070 21 : if (bAnswer)
3071 0 : return true;
3072 : }
3073 21 : return false;
3074 : }
3075 :
3076 2 : void ScDocument::MixDocument( const ScRange& rRange, sal_uInt16 nFunction, bool bSkipEmpty,
3077 : ScDocument* pSrcDoc )
3078 : {
3079 2 : SCTAB nTab1 = rRange.aStart.Tab();
3080 2 : SCTAB nTab2 = rRange.aEnd.Tab();
3081 2 : sc::MixDocContext aCxt(*this);
3082 2 : SCTAB nMinSizeBothTabs = static_cast<SCTAB>(std::min(maTabs.size(), pSrcDoc->maTabs.size()));
3083 4 : for (SCTAB i = nTab1; i <= nTab2 && i < nMinSizeBothTabs; i++)
3084 : {
3085 2 : ScTable* pTab = FetchTable(i);
3086 2 : const ScTable* pSrcTab = pSrcDoc->FetchTable(i);
3087 2 : if (!pTab || !pSrcTab)
3088 0 : continue;
3089 :
3090 : pTab->MixData(
3091 4 : aCxt, rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(),
3092 6 : nFunction, bSkipEmpty, pSrcTab);
3093 2 : }
3094 2 : }
3095 :
3096 0 : void ScDocument::FillTab( const ScRange& rSrcArea, const ScMarkData& rMark,
3097 : InsertDeleteFlags nFlags, sal_uInt16 nFunction,
3098 : bool bSkipEmpty, bool bAsLink )
3099 : {
3100 0 : InsertDeleteFlags nDelFlags = nFlags;
3101 0 : if (nDelFlags & IDF_CONTENTS)
3102 0 : nDelFlags |= IDF_CONTENTS; // Either all contents or delete nothing!
3103 :
3104 0 : SCTAB nSrcTab = rSrcArea.aStart.Tab();
3105 :
3106 0 : if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab])
3107 : {
3108 0 : SCCOL nStartCol = rSrcArea.aStart.Col();
3109 0 : SCROW nStartRow = rSrcArea.aStart.Row();
3110 0 : SCCOL nEndCol = rSrcArea.aEnd.Col();
3111 0 : SCROW nEndRow = rSrcArea.aEnd.Row();
3112 0 : boost::scoped_ptr<ScDocument> pMixDoc;
3113 0 : bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
3114 :
3115 0 : bool bOldAutoCalc = GetAutoCalc();
3116 0 : SetAutoCalc( false ); // avoid multiple calculations
3117 :
3118 0 : sc::CopyToDocContext aCxt(*this);
3119 0 : sc::MixDocContext aMixDocCxt(*this);
3120 :
3121 0 : SCTAB nCount = static_cast<SCTAB>(maTabs.size());
3122 0 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
3123 0 : for (; itr != itrEnd && *itr < nCount; ++itr)
3124 0 : if ( *itr!=nSrcTab && maTabs[*itr])
3125 : {
3126 0 : SCTAB i = *itr;
3127 0 : if (bDoMix)
3128 : {
3129 0 : if (!pMixDoc)
3130 : {
3131 0 : pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
3132 0 : pMixDoc->InitUndo( this, i, i );
3133 : }
3134 : else
3135 0 : pMixDoc->AddUndoTab( i, i );
3136 :
3137 : // context used for copying content to the temporary mix document.
3138 0 : sc::CopyToDocContext aMixCxt(*pMixDoc);
3139 0 : maTabs[i]->CopyToTable(aMixCxt, nStartCol,nStartRow, nEndCol,nEndRow,
3140 0 : IDF_CONTENTS, false, pMixDoc->maTabs[i] );
3141 : }
3142 0 : maTabs[i]->DeleteArea( nStartCol,nStartRow, nEndCol,nEndRow, nDelFlags);
3143 0 : maTabs[nSrcTab]->CopyToTable(aCxt, nStartCol,nStartRow, nEndCol,nEndRow,
3144 0 : nFlags, false, maTabs[i], NULL, bAsLink );
3145 :
3146 0 : if (bDoMix)
3147 0 : maTabs[i]->MixData(aMixDocCxt, nStartCol,nStartRow, nEndCol,nEndRow,
3148 0 : nFunction, bSkipEmpty, pMixDoc->maTabs[i] );
3149 : }
3150 :
3151 0 : SetAutoCalc( bOldAutoCalc );
3152 : }
3153 : else
3154 : {
3155 : OSL_FAIL("wrong table");
3156 : }
3157 0 : }
3158 :
3159 0 : void ScDocument::FillTabMarked( SCTAB nSrcTab, const ScMarkData& rMark,
3160 : InsertDeleteFlags nFlags, sal_uInt16 nFunction,
3161 : bool bSkipEmpty, bool bAsLink )
3162 : {
3163 0 : InsertDeleteFlags nDelFlags = nFlags;
3164 0 : if (nDelFlags & IDF_CONTENTS)
3165 0 : nDelFlags |= IDF_CONTENTS; // Either all contents or delete nothing!
3166 :
3167 0 : if (ValidTab(nSrcTab) && nSrcTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nSrcTab])
3168 : {
3169 0 : boost::scoped_ptr<ScDocument> pMixDoc;
3170 0 : bool bDoMix = ( bSkipEmpty || nFunction ) && ( nFlags & IDF_CONTENTS );
3171 :
3172 0 : bool bOldAutoCalc = GetAutoCalc();
3173 0 : SetAutoCalc( false ); // avoid multiple calculations
3174 :
3175 0 : ScRange aArea;
3176 0 : rMark.GetMultiMarkArea( aArea );
3177 0 : SCCOL nStartCol = aArea.aStart.Col();
3178 0 : SCROW nStartRow = aArea.aStart.Row();
3179 0 : SCCOL nEndCol = aArea.aEnd.Col();
3180 0 : SCROW nEndRow = aArea.aEnd.Row();
3181 :
3182 0 : sc::CopyToDocContext aCxt(*this);
3183 0 : sc::MixDocContext aMixDocCxt(*this);
3184 0 : SCTAB nCount = static_cast<SCTAB>(maTabs.size());
3185 0 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
3186 0 : for (; itr != itrEnd && *itr < nCount; ++itr)
3187 0 : if ( *itr!=nSrcTab && maTabs[*itr] )
3188 : {
3189 0 : SCTAB i = *itr;
3190 0 : if (bDoMix)
3191 : {
3192 0 : if (!pMixDoc)
3193 : {
3194 0 : pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
3195 0 : pMixDoc->InitUndo( this, i, i );
3196 : }
3197 : else
3198 0 : pMixDoc->AddUndoTab( i, i );
3199 :
3200 0 : sc::CopyToDocContext aMixCxt(*pMixDoc);
3201 0 : maTabs[i]->CopyToTable(aMixCxt, nStartCol,nStartRow, nEndCol,nEndRow,
3202 0 : IDF_CONTENTS, true, pMixDoc->maTabs[i], &rMark );
3203 : }
3204 :
3205 0 : maTabs[i]->DeleteSelection( nDelFlags, rMark );
3206 0 : maTabs[nSrcTab]->CopyToTable(aCxt, nStartCol,nStartRow, nEndCol,nEndRow,
3207 0 : nFlags, true, maTabs[i], &rMark, bAsLink );
3208 :
3209 0 : if (bDoMix)
3210 0 : maTabs[i]->MixMarked(aMixDocCxt, rMark, nFunction, bSkipEmpty, pMixDoc->maTabs[i]);
3211 : }
3212 :
3213 0 : SetAutoCalc( bOldAutoCalc );
3214 : }
3215 : else
3216 : {
3217 : OSL_FAIL("wrong table");
3218 : }
3219 0 : }
3220 :
3221 6091 : bool ScDocument::SetString( SCCOL nCol, SCROW nRow, SCTAB nTab, const OUString& rString,
3222 : ScSetStringParam* pParam )
3223 : {
3224 6091 : ScTable* pTab = FetchTable(nTab);
3225 6091 : if (!pTab)
3226 0 : return false;
3227 :
3228 6091 : bool bNumFmtSet = false;
3229 :
3230 6091 : const ScFormulaCell* pCurCellFormula = pTab->GetFormulaCell(nCol, nRow);
3231 6091 : if (pCurCellFormula && pCurCellFormula->IsShared())
3232 : {
3233 : // In case setting this string affects an existing formula group, record
3234 : // its above and below position for later listening.
3235 :
3236 22 : std::vector<ScAddress> aGroupPos;
3237 44 : sc::EndListeningContext aCxt(*this);
3238 22 : ScAddress aPos(nCol, nRow, nTab);
3239 22 : EndListeningIntersectedGroup(aCxt, aPos, &aGroupPos);
3240 22 : aCxt.purgeEmptyBroadcasters();
3241 :
3242 22 : bNumFmtSet = pTab->SetString(nCol, nRow, nTab, rString, pParam);
3243 :
3244 22 : SetNeedsListeningGroups(aGroupPos);
3245 44 : StartNeededListeners();
3246 : }
3247 : else
3248 : {
3249 6069 : bNumFmtSet = pTab->SetString(nCol, nRow, nTab, rString, pParam);
3250 : }
3251 :
3252 6091 : return bNumFmtSet;
3253 : }
3254 :
3255 2315 : bool ScDocument::SetString(
3256 : const ScAddress& rPos, const OUString& rString, ScSetStringParam* pParam )
3257 : {
3258 2315 : return SetString(rPos.Col(), rPos.Row(), rPos.Tab(), rString, pParam);
3259 : }
3260 :
3261 195 : bool ScDocument::SetEditText( const ScAddress& rPos, EditTextObject* pEditText )
3262 : {
3263 195 : if (!TableExists(rPos.Tab()))
3264 : {
3265 0 : delete pEditText;
3266 0 : return false;
3267 : }
3268 :
3269 195 : return maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), pEditText);
3270 : }
3271 :
3272 0 : void ScDocument::SetEditText( const ScAddress& rPos, const EditTextObject& rEditText, const SfxItemPool* pEditPool )
3273 : {
3274 0 : if (!TableExists(rPos.Tab()))
3275 0 : return;
3276 :
3277 0 : maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEditText, pEditPool);
3278 : }
3279 :
3280 0 : void ScDocument::SetEditText( const ScAddress& rPos, const OUString& rStr )
3281 : {
3282 0 : if (!TableExists(rPos.Tab()))
3283 0 : return;
3284 :
3285 0 : ScFieldEditEngine& rEngine = GetEditEngine();
3286 0 : rEngine.SetText(rStr);
3287 0 : maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEngine.CreateTextObject());
3288 : }
3289 :
3290 11 : SCROW ScDocument::GetFirstEditTextRow( const ScRange& rRange ) const
3291 : {
3292 11 : const ScTable* pTab = FetchTable(rRange.aStart.Tab());
3293 11 : if (!pTab)
3294 0 : return -1;
3295 :
3296 11 : return pTab->GetFirstEditTextRow(rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
3297 : }
3298 :
3299 944 : void ScDocument::SetTextCell( const ScAddress& rPos, const OUString& rStr )
3300 : {
3301 944 : if (!TableExists(rPos.Tab()))
3302 944 : return;
3303 :
3304 944 : if (ScStringUtil::isMultiline(rStr))
3305 : {
3306 0 : ScFieldEditEngine& rEngine = GetEditEngine();
3307 0 : rEngine.SetText(rStr);
3308 0 : maTabs[rPos.Tab()]->SetEditText(rPos.Col(), rPos.Row(), rEngine.CreateTextObject());
3309 : }
3310 : else
3311 : {
3312 944 : ScSetStringParam aParam;
3313 944 : aParam.setTextInput();
3314 944 : maTabs[rPos.Tab()]->SetString(rPos.Col(), rPos.Row(), rPos.Tab(), rStr, &aParam);
3315 : }
3316 : }
3317 :
3318 490 : void ScDocument::SetEmptyCell( const ScAddress& rPos )
3319 : {
3320 490 : if (!TableExists(rPos.Tab()))
3321 490 : return;
3322 :
3323 490 : maTabs[rPos.Tab()]->SetEmptyCell(rPos.Col(), rPos.Row());
3324 : }
3325 :
3326 2376 : void ScDocument::SetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rVal )
3327 : {
3328 2376 : SetValue(ScAddress(nCol, nRow, nTab), rVal);
3329 2376 : }
3330 :
3331 26522 : void ScDocument::SetValue( const ScAddress& rPos, double fVal )
3332 : {
3333 26522 : ScTable* pTab = FetchTable(rPos.Tab());
3334 26522 : if (!pTab)
3335 26522 : return;
3336 :
3337 26522 : const ScFormulaCell* pCurCellFormula = pTab->GetFormulaCell(rPos.Col(), rPos.Row());
3338 26522 : if (pCurCellFormula && pCurCellFormula->IsShared())
3339 : {
3340 : // In case setting this string affects an existing formula group, record
3341 : // its above and below position for later listening.
3342 :
3343 14 : std::vector<ScAddress> aGroupPos;
3344 28 : sc::EndListeningContext aCxt(*this);
3345 14 : EndListeningIntersectedGroup(aCxt, rPos, &aGroupPos);
3346 14 : aCxt.purgeEmptyBroadcasters();
3347 :
3348 14 : pTab->SetValue(rPos.Col(), rPos.Row(), fVal);
3349 :
3350 14 : SetNeedsListeningGroups(aGroupPos);
3351 28 : StartNeededListeners();
3352 : }
3353 : else
3354 : {
3355 26508 : pTab->SetValue(rPos.Col(), rPos.Row(), fVal);
3356 : }
3357 : }
3358 :
3359 10507 : OUString ScDocument::GetString( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3360 : {
3361 10507 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
3362 : {
3363 10507 : OUString aStr;
3364 10507 : maTabs[nTab]->GetString(nCol, nRow, aStr);
3365 10507 : return aStr;
3366 : }
3367 : else
3368 0 : return EMPTY_OUSTRING;
3369 : }
3370 :
3371 8125 : OUString ScDocument::GetString( const ScAddress& rPos ) const
3372 : {
3373 8125 : if (!TableExists(rPos.Tab()))
3374 0 : return EMPTY_OUSTRING;
3375 :
3376 8125 : OUString aStr;
3377 8125 : maTabs[rPos.Tab()]->GetString(rPos.Col(), rPos.Row(), aStr);
3378 8125 : return aStr;
3379 : }
3380 :
3381 5 : double* ScDocument::GetValueCell( const ScAddress& rPos )
3382 : {
3383 5 : if (!TableExists(rPos.Tab()))
3384 0 : return NULL;
3385 :
3386 5 : return maTabs[rPos.Tab()]->GetValueCell(rPos.Col(), rPos.Row());
3387 : }
3388 :
3389 34 : svl::SharedString ScDocument::GetSharedString( const ScAddress& rPos ) const
3390 : {
3391 34 : if (!TableExists(rPos.Tab()))
3392 0 : return svl::SharedString();
3393 :
3394 34 : return maTabs[rPos.Tab()]->GetSharedString(rPos.Col(), rPos.Row());
3395 : }
3396 :
3397 22 : sc::FormulaGroupContext& ScDocument::GetFormulaGroupContext()
3398 : {
3399 22 : if (!mpFormulaGroupCxt)
3400 8 : mpFormulaGroupCxt.reset(new sc::FormulaGroupContext);
3401 :
3402 22 : return *mpFormulaGroupCxt;
3403 : }
3404 :
3405 3097 : void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rString )
3406 : {
3407 3097 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3408 3097 : maTabs[nTab]->GetInputString( nCol, nRow, rString );
3409 : else
3410 0 : rString.clear();
3411 3097 : }
3412 :
3413 48 : sal_uInt16 ScDocument::GetStringForFormula( const ScAddress& rPos, OUString& rString )
3414 : {
3415 : // Used in formulas (add-in parameters etc), so it must use the same semantics as
3416 : // ScInterpreter::GetCellString: always format values as numbers.
3417 : // The return value is the error code.
3418 :
3419 48 : ScRefCellValue aCell;
3420 48 : aCell.assign(*this, rPos);
3421 48 : if (aCell.isEmpty())
3422 : {
3423 0 : rString = EMPTY_OUSTRING;
3424 0 : return 0;
3425 : }
3426 :
3427 48 : sal_uInt16 nErr = 0;
3428 96 : OUString aStr;
3429 48 : SvNumberFormatter* pFormatter = GetFormatTable();
3430 48 : switch (aCell.meType)
3431 : {
3432 : case CELLTYPE_STRING:
3433 : case CELLTYPE_EDIT:
3434 48 : aStr = aCell.getString(this);
3435 48 : break;
3436 : case CELLTYPE_FORMULA:
3437 : {
3438 0 : ScFormulaCell* pFCell = aCell.mpFormula;
3439 0 : nErr = pFCell->GetErrCode();
3440 0 : if (pFCell->IsValue())
3441 : {
3442 0 : double fVal = pFCell->GetValue();
3443 : sal_uInt32 nIndex = pFormatter->GetStandardFormat(
3444 : css::util::NumberFormat::NUMBER,
3445 0 : ScGlobal::eLnge);
3446 0 : pFormatter->GetInputLineString(fVal, nIndex, aStr);
3447 : }
3448 : else
3449 0 : aStr = pFCell->GetString().getString();
3450 : }
3451 0 : break;
3452 : case CELLTYPE_VALUE:
3453 : {
3454 0 : double fVal = aCell.mfValue;
3455 : sal_uInt32 nIndex = pFormatter->GetStandardFormat(
3456 : css::util::NumberFormat::NUMBER,
3457 0 : ScGlobal::eLnge);
3458 0 : pFormatter->GetInputLineString(fVal, nIndex, aStr);
3459 : }
3460 0 : break;
3461 : default:
3462 : ;
3463 : }
3464 :
3465 48 : rString = aStr;
3466 96 : return nErr;
3467 : }
3468 :
3469 473 : void ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab, double& rValue ) const
3470 : {
3471 473 : if (TableExists(nTab))
3472 473 : rValue = maTabs[nTab]->GetValue( nCol, nRow );
3473 : else
3474 0 : rValue = 0.0;
3475 473 : }
3476 :
3477 76 : const EditTextObject* ScDocument::GetEditText( const ScAddress& rPos ) const
3478 : {
3479 76 : SCTAB nTab = rPos.Tab();
3480 76 : if (!TableExists(nTab))
3481 0 : return NULL;
3482 :
3483 76 : return maTabs[nTab]->GetEditText(rPos.Col(), rPos.Row());
3484 : }
3485 :
3486 0 : void ScDocument::RemoveEditTextCharAttribs( const ScAddress& rPos, const ScPatternAttr& rAttr )
3487 : {
3488 0 : if (!TableExists(rPos.Tab()))
3489 0 : return;
3490 :
3491 0 : return maTabs[rPos.Tab()]->RemoveEditTextCharAttribs(rPos.Col(), rPos.Row(), rAttr);
3492 : }
3493 :
3494 13375 : double ScDocument::GetValue( const ScAddress& rPos ) const
3495 : {
3496 13375 : SCTAB nTab = rPos.Tab();
3497 13375 : if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3498 13375 : return maTabs[nTab]->GetValue(rPos.Col(), rPos.Row());
3499 0 : return 0.0;
3500 : }
3501 :
3502 346 : double ScDocument::GetValue( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3503 : {
3504 346 : ScAddress aAdr(nCol, nRow, nTab); return GetValue(aAdr);
3505 : }
3506 :
3507 1056 : void ScDocument::GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab,
3508 : sal_uInt32& rFormat ) const
3509 : {
3510 1056 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
3511 1056 : if (maTabs[nTab])
3512 : {
3513 1056 : rFormat = maTabs[nTab]->GetNumberFormat( nCol, nRow );
3514 2112 : return ;
3515 : }
3516 0 : rFormat = 0;
3517 : }
3518 :
3519 0 : sal_uInt32 ScDocument::GetNumberFormat( const ScRange& rRange ) const
3520 : {
3521 0 : SCTAB nTab1 = rRange.aStart.Tab(), nTab2 = rRange.aEnd.Tab();
3522 0 : SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
3523 0 : SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
3524 :
3525 0 : if (!ValidTab(nTab1) || !ValidTab(nTab2) || !maTabs[nTab1] || !maTabs[nTab2])
3526 0 : return 0;
3527 :
3528 0 : sal_uInt32 nFormat = 0;
3529 0 : bool bFirstItem = true;
3530 0 : for (SCTAB nTab = nTab1; nTab <= nTab2 && nTab < static_cast<SCTAB>(maTabs.size()) ; ++nTab)
3531 0 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
3532 : {
3533 0 : sal_uInt32 nThisFormat = maTabs[nTab]->GetNumberFormat(nCol, nRow1, nRow2);
3534 0 : if (bFirstItem)
3535 : {
3536 0 : nFormat = nThisFormat;
3537 0 : bFirstItem = false;
3538 : }
3539 0 : else if (nThisFormat != nFormat)
3540 0 : return 0;
3541 : }
3542 :
3543 0 : return nFormat;
3544 : }
3545 :
3546 19062 : sal_uInt32 ScDocument::GetNumberFormat( const ScAddress& rPos ) const
3547 : {
3548 19062 : SCTAB nTab = rPos.Tab();
3549 19062 : if (!TableExists(nTab))
3550 0 : return 0;
3551 :
3552 19062 : return maTabs[nTab]->GetNumberFormat( rPos );
3553 : }
3554 :
3555 67 : void ScDocument::SetNumberFormat( const ScAddress& rPos, sal_uInt32 nNumberFormat )
3556 : {
3557 67 : SCTAB nTab = rPos.Tab();
3558 67 : if (!TableExists(nTab))
3559 67 : return;
3560 :
3561 67 : maTabs[nTab]->SetNumberFormat(rPos.Col(), rPos.Row(), nNumberFormat);
3562 : }
3563 :
3564 4895 : void ScDocument::GetNumberFormatInfo( short& nType, sal_uLong& nIndex,
3565 : const ScAddress& rPos ) const
3566 : {
3567 4895 : SCTAB nTab = rPos.Tab();
3568 4895 : if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3569 : {
3570 4895 : nIndex = maTabs[nTab]->GetNumberFormat( rPos );
3571 4895 : nType = GetFormatTable()->GetType( nIndex );
3572 : }
3573 : else
3574 : {
3575 0 : nType = css::util::NumberFormat::UNDEFINED;
3576 0 : nIndex = 0;
3577 : }
3578 4895 : }
3579 :
3580 62 : void ScDocument::GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rFormula ) const
3581 : {
3582 62 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3583 62 : maTabs[nTab]->GetFormula( nCol, nRow, rFormula );
3584 : else
3585 0 : rFormula.clear();
3586 62 : }
3587 :
3588 0 : const ScFormulaCell* ScDocument::GetFormulaCell( const ScAddress& rPos ) const
3589 : {
3590 0 : if (!TableExists(rPos.Tab()))
3591 0 : return NULL;
3592 :
3593 0 : return maTabs[rPos.Tab()]->GetFormulaCell(rPos.Col(), rPos.Row());
3594 : }
3595 :
3596 4931 : ScFormulaCell* ScDocument::GetFormulaCell( const ScAddress& rPos )
3597 : {
3598 4931 : if (!TableExists(rPos.Tab()))
3599 0 : return NULL;
3600 :
3601 4931 : return maTabs[rPos.Tab()]->GetFormulaCell(rPos.Col(), rPos.Row());
3602 : }
3603 :
3604 27606 : CellType ScDocument::GetCellType( const ScAddress& rPos ) const
3605 : {
3606 27606 : SCTAB nTab = rPos.Tab();
3607 27606 : if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3608 27606 : return maTabs[nTab]->GetCellType( rPos );
3609 0 : return CELLTYPE_NONE;
3610 : }
3611 :
3612 20 : void ScDocument::GetCellType( SCCOL nCol, SCROW nRow, SCTAB nTab,
3613 : CellType& rCellType ) const
3614 : {
3615 20 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
3616 20 : rCellType = maTabs[nTab]->GetCellType( nCol, nRow );
3617 : else
3618 0 : rCellType = CELLTYPE_NONE;
3619 20 : }
3620 :
3621 4 : bool ScDocument::HasStringData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3622 : {
3623 4 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3624 4 : return maTabs[nTab]->HasStringData( nCol, nRow );
3625 : else
3626 0 : return false;
3627 : }
3628 :
3629 2969 : bool ScDocument::HasValueData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3630 : {
3631 2969 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3632 2969 : return maTabs[nTab]->HasValueData( nCol, nRow );
3633 : else
3634 0 : return false;
3635 : }
3636 :
3637 0 : bool ScDocument::HasValueData( const ScAddress& rPos ) const
3638 : {
3639 0 : return HasValueData(rPos.Col(), rPos.Row(), rPos.Tab());
3640 : }
3641 :
3642 0 : bool ScDocument::HasStringCells( const ScRange& rRange ) const
3643 : {
3644 : // true, if String- or Edit cells in range
3645 :
3646 0 : SCCOL nStartCol = rRange.aStart.Col();
3647 0 : SCROW nStartRow = rRange.aStart.Row();
3648 0 : SCTAB nStartTab = rRange.aStart.Tab();
3649 0 : SCCOL nEndCol = rRange.aEnd.Col();
3650 0 : SCROW nEndRow = rRange.aEnd.Row();
3651 0 : SCTAB nEndTab = rRange.aEnd.Tab();
3652 :
3653 0 : for ( SCTAB nTab=nStartTab; nTab<=nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
3654 0 : if ( maTabs[nTab] && maTabs[nTab]->HasStringCells( nStartCol, nStartRow, nEndCol, nEndRow ) )
3655 0 : return true;
3656 :
3657 0 : return false;
3658 : }
3659 :
3660 0 : bool ScDocument::HasSelectionData( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
3661 : {
3662 0 : sal_uInt32 nValidation = static_cast< const SfxUInt32Item* >( GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA ) )->GetValue();
3663 0 : if( nValidation )
3664 : {
3665 0 : const ScValidationData* pData = GetValidationEntry( nValidation );
3666 0 : if( pData && pData->HasSelectionList() )
3667 0 : return true;
3668 : }
3669 0 : return HasStringCells( ScRange( nCol, 0, nTab, nCol, MAXROW, nTab ) );
3670 : }
3671 :
3672 597 : void ScDocument::SetAllFormulasDirty( const sc::SetFormulaDirtyContext& rCxt )
3673 : {
3674 597 : bool bOldAutoCalc = GetAutoCalc();
3675 597 : bAutoCalc = false; // no mulitple calculations
3676 : { // scope for bulk broadcast
3677 597 : ScBulkBroadcast aBulkBroadcast( GetBASM());
3678 597 : TableContainer::iterator it = maTabs.begin();
3679 1700 : for (;it != maTabs.end(); ++it)
3680 1103 : if (*it)
3681 1700 : (*it)->SetAllFormulasDirty(rCxt);
3682 : }
3683 :
3684 : // Allthough Charts are also set to dirty in Tracking without AutoCalc
3685 : // if all formulas are dirty, the charts can no longer be caught
3686 : // (#45205#) - that is why all Charts have to be explicitly handled again
3687 597 : if (pChartListenerCollection)
3688 597 : pChartListenerCollection->SetDirty();
3689 :
3690 597 : SetAutoCalc( bOldAutoCalc );
3691 597 : }
3692 :
3693 200 : void ScDocument::SetDirty( const ScRange& rRange, bool bIncludeEmptyCells )
3694 : {
3695 200 : bool bOldAutoCalc = GetAutoCalc();
3696 200 : bAutoCalc = false; // no mulitple calculations
3697 : { // scope for bulk broadcast
3698 200 : ScBulkBroadcast aBulkBroadcast( GetBASM());
3699 200 : SCTAB nTab2 = rRange.aEnd.Tab();
3700 400 : for (SCTAB i=rRange.aStart.Tab(); i<=nTab2 && i < static_cast<SCTAB>(maTabs.size()); i++)
3701 400 : if (maTabs[i]) maTabs[i]->SetDirty( rRange,
3702 400 : (bIncludeEmptyCells ? ScColumn::BROADCAST_BROADCASTERS : ScColumn::BROADCAST_DATA_POSITIONS));
3703 :
3704 : /* TODO: this now also notifies conditional formatting and does an UNO
3705 : * broadcast, which wasn't done here before. Is that an actually
3706 : * desired side effect, or should we come up with a method that
3707 : * doesn't? */
3708 200 : if (bIncludeEmptyCells)
3709 53 : BroadcastCells( rRange, SC_HINT_DATACHANGED, false);
3710 : }
3711 200 : SetAutoCalc( bOldAutoCalc );
3712 200 : }
3713 :
3714 44 : void ScDocument::SetTableOpDirty( const ScRange& rRange )
3715 : {
3716 44 : bool bOldAutoCalc = GetAutoCalc();
3717 44 : bAutoCalc = false; // no multiple recalculation
3718 44 : SCTAB nTab2 = rRange.aEnd.Tab();
3719 88 : for (SCTAB i=rRange.aStart.Tab(); i<=nTab2 && i < static_cast<SCTAB>(maTabs.size()); i++)
3720 44 : if (maTabs[i]) maTabs[i]->SetTableOpDirty( rRange );
3721 44 : SetAutoCalc( bOldAutoCalc );
3722 44 : }
3723 :
3724 2940 : void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges )
3725 : {
3726 2940 : if (!GetAutoCalc())
3727 0 : return;
3728 :
3729 2940 : mpFormulaGroupCxt.reset();
3730 :
3731 5885 : for (size_t nPos=0, nRangeCount = rRanges.size(); nPos < nRangeCount; nPos++)
3732 : {
3733 2945 : const ScRange& rRange = *rRanges[nPos];
3734 5890 : for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
3735 : {
3736 2945 : ScTable* pTab = FetchTable(nTab);
3737 2945 : if (!pTab)
3738 0 : return;
3739 :
3740 : pTab->InterpretDirtyCells(
3741 2945 : rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
3742 : }
3743 : }
3744 :
3745 2940 : mpFormulaGroupCxt.reset();
3746 : }
3747 :
3748 21264 : void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell )
3749 : {
3750 21264 : if ( !aTableOpList.empty() )
3751 : {
3752 21087 : ScInterpreterTableOpParams* p = &aTableOpList.back();
3753 21087 : if ( p->bCollectNotifications )
3754 : {
3755 21087 : if ( p->bRefresh )
3756 : { // refresh pointers only
3757 20903 : p->aNotifiedFormulaCells.push_back( pCell );
3758 : }
3759 : else
3760 : { // init both, address and pointer
3761 184 : p->aNotifiedFormulaCells.push_back( pCell );
3762 184 : p->aNotifiedFormulaPos.push_back( pCell->aPos );
3763 : }
3764 : }
3765 : }
3766 21264 : }
3767 :
3768 349 : void ScDocument::CalcAll()
3769 : {
3770 349 : ClearFormulaContext();
3771 349 : ClearLookupCaches(); // Ensure we don't deliver zombie data.
3772 349 : sc::AutoCalcSwitch aSwitch(*this, true);
3773 349 : TableContainer::iterator it = maTabs.begin();
3774 1001 : for (; it != maTabs.end(); ++it)
3775 652 : if (*it)
3776 652 : (*it)->SetDirtyVar();
3777 1001 : for (it = maTabs.begin(); it != maTabs.end(); ++it)
3778 652 : if (*it)
3779 652 : (*it)->CalcAll();
3780 349 : ClearFormulaTree();
3781 349 : }
3782 :
3783 3 : void ScDocument::CompileAll()
3784 : {
3785 3 : sc::CompileFormulaContext aCxt(this);
3786 3 : TableContainer::iterator it = maTabs.begin();
3787 6 : for (; it != maTabs.end(); ++it)
3788 3 : if (*it)
3789 3 : (*it)->CompileAll(aCxt);
3790 :
3791 3 : sc::SetFormulaDirtyContext aFormulaDirtyCxt;
3792 3 : SetAllFormulasDirty(aFormulaDirtyCxt);
3793 3 : }
3794 :
3795 : namespace {
3796 :
3797 : class CompileXMLHandler : std::unary_function<ScTable*, void>
3798 : {
3799 : sc::CompileFormulaContext* mpCxt;
3800 : ScProgress* mpProgress;
3801 : public:
3802 197 : CompileXMLHandler( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ) :
3803 197 : mpCxt(&rCxt), mpProgress(&rProgress) {} // Take pointers to make it copyable.
3804 :
3805 331 : void operator() ( ScTable* pTab )
3806 : {
3807 331 : if (pTab)
3808 331 : pTab->CompileXML(*mpCxt, *mpProgress);
3809 331 : }
3810 : };
3811 :
3812 : }
3813 :
3814 197 : void ScDocument::CompileXML()
3815 : {
3816 197 : bool bOldAutoCalc = GetAutoCalc();
3817 197 : SetAutoCalc( false );
3818 : ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(
3819 197 : STR_PROGRESS_CALCULATING ), GetXMLImportedFormulaCount() );
3820 :
3821 394 : sc::CompileFormulaContext aCxt(this);
3822 :
3823 : // set AutoNameCache to speed up automatic name lookup
3824 : OSL_ENSURE( !pAutoNameCache, "AutoNameCache already set" );
3825 197 : pAutoNameCache = new ScAutoNameCache( this );
3826 :
3827 197 : if (pRangeName)
3828 40 : pRangeName->CompileUnresolvedXML(aCxt);
3829 :
3830 197 : std::for_each(maTabs.begin(), maTabs.end(), CompileXMLHandler(aCxt, aProgress));
3831 197 : StartAllListeners();
3832 :
3833 197 : DELETEZ( pAutoNameCache ); // valid only during CompileXML, where cell contents don't change
3834 :
3835 197 : if ( pValidationList )
3836 1 : pValidationList->CompileXML();
3837 :
3838 : // Track all formula cells that were appended to the FormulaTrack during
3839 : // import or CompileXML().
3840 197 : TrackFormulas();
3841 :
3842 394 : SetAutoCalc( bOldAutoCalc );
3843 197 : }
3844 :
3845 0 : bool ScDocument::CompileErrorCells(sal_uInt16 nErrCode)
3846 : {
3847 0 : bool bCompiled = false;
3848 0 : sc::CompileFormulaContext aCxt(this);
3849 0 : TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
3850 0 : for (; it != itEnd; ++it)
3851 : {
3852 0 : ScTable* pTab = *it;
3853 0 : if (!pTab)
3854 0 : continue;
3855 :
3856 0 : if (pTab->CompileErrorCells(aCxt, nErrCode))
3857 0 : bCompiled = true;
3858 : }
3859 :
3860 0 : return bCompiled;
3861 : }
3862 :
3863 90 : void ScDocument::CalcAfterLoad( bool bStartListening )
3864 : {
3865 90 : if (bIsClip) // Excel data is loaded from the Clipboard to a Clip-Doc
3866 90 : return; // the clculation is then only perfromed when inserting into the real document
3867 :
3868 90 : bCalcingAfterLoad = true;
3869 90 : sc::CompileFormulaContext aCxt(this);
3870 : {
3871 90 : TableContainer::iterator it = maTabs.begin();
3872 323 : for (; it != maTabs.end(); ++it)
3873 233 : if (*it)
3874 233 : (*it)->CalcAfterLoad(aCxt, bStartListening);
3875 323 : for (it = maTabs.begin(); it != maTabs.end(); ++it)
3876 233 : if (*it)
3877 233 : (*it)->SetDirtyAfterLoad();
3878 : }
3879 90 : bCalcingAfterLoad = false;
3880 :
3881 90 : SetDetectiveDirty(false); // No real changes yet
3882 :
3883 : // #i112436# If formula cells are already dirty, they don't broadcast further changes.
3884 : // So the source ranges of charts must be interpreted even if they are not visible,
3885 : // similar to ScMyShapeResizer::CreateChartListener for loading own files (i104899).
3886 90 : if (pChartListenerCollection)
3887 : {
3888 90 : const ScChartListenerCollection::ListenersType& rListeners = pChartListenerCollection->getListeners();
3889 90 : ScChartListenerCollection::ListenersType::const_iterator it = rListeners.begin(), itEnd = rListeners.end();
3890 136 : for (; it != itEnd; ++it)
3891 : {
3892 46 : const ScChartListener* p = it->second;
3893 46 : InterpretDirtyCells(*p->GetRangeList());
3894 : }
3895 90 : }
3896 : }
3897 :
3898 2478 : sal_uInt16 ScDocument::GetErrCode( const ScAddress& rPos ) const
3899 : {
3900 2478 : SCTAB nTab = rPos.Tab();
3901 2478 : if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3902 2478 : return maTabs[nTab]->GetErrCode( rPos );
3903 0 : return 0;
3904 : }
3905 :
3906 2964 : void ScDocument::ResetChanged( const ScRange& rRange )
3907 : {
3908 2964 : SCTAB nTabSize = static_cast<SCTAB>(maTabs.size());
3909 2964 : SCTAB nTab1 = rRange.aStart.Tab();
3910 2964 : SCTAB nTab2 = rRange.aEnd.Tab();
3911 6872 : for (SCTAB nTab = nTab1; nTab1 <= nTab2 && nTab < nTabSize; ++nTab)
3912 3908 : if (maTabs[nTab])
3913 3908 : maTabs[nTab]->ResetChanged(rRange);
3914 2964 : }
3915 :
3916 : // Column widths / Row heights --------------------------------------
3917 :
3918 17656 : void ScDocument::SetColWidth( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth )
3919 : {
3920 17656 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3921 17656 : maTabs[nTab]->SetColWidth( nCol, nNewWidth );
3922 17656 : }
3923 :
3924 504832 : void ScDocument::SetColWidthOnly( SCCOL nCol, SCTAB nTab, sal_uInt16 nNewWidth )
3925 : {
3926 504832 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3927 504832 : maTabs[nTab]->SetColWidthOnly( nCol, nNewWidth );
3928 504832 : }
3929 :
3930 1 : void ScDocument::SetRowHeight( SCROW nRow, SCTAB nTab, sal_uInt16 nNewHeight )
3931 : {
3932 1 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3933 1 : maTabs[nTab]->SetRowHeight( nRow, nNewHeight );
3934 1 : }
3935 :
3936 5 : void ScDocument::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight )
3937 : {
3938 5 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3939 5 : maTabs[nTab]->SetRowHeightRange
3940 10 : ( nStartRow, nEndRow, nNewHeight, 1.0, 1.0 );
3941 5 : }
3942 :
3943 5895 : void ScDocument::SetRowHeightOnly( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt16 nNewHeight )
3944 : {
3945 5895 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3946 5895 : maTabs[nTab]->SetRowHeightOnly( nStartRow, nEndRow, nNewHeight );
3947 5895 : }
3948 :
3949 405 : void ScDocument::SetManualHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bManual )
3950 : {
3951 405 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3952 405 : maTabs[nTab]->SetManualHeight( nStartRow, nEndRow, bManual );
3953 405 : }
3954 :
3955 1081166 : sal_uInt16 ScDocument::GetColWidth( SCCOL nCol, SCTAB nTab, bool bHiddenAsZero ) const
3956 : {
3957 1081166 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3958 1081166 : return maTabs[nTab]->GetColWidth( nCol, bHiddenAsZero );
3959 : OSL_FAIL("wrong table number");
3960 0 : return 0;
3961 : }
3962 :
3963 0 : sal_uLong ScDocument::GetColWidth( SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHiddenAsZero ) const
3964 : {
3965 0 : const ScTable* pTab = FetchTable(nTab);
3966 0 : if (!pTab)
3967 0 : return 0;
3968 :
3969 0 : return pTab->GetColWidth(nStartCol, nEndCol, bHiddenAsZero);
3970 : }
3971 :
3972 785 : sal_uInt16 ScDocument::GetOriginalWidth( SCCOL nCol, SCTAB nTab ) const
3973 : {
3974 785 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3975 785 : return maTabs[nTab]->GetOriginalWidth( nCol );
3976 : OSL_FAIL("wrong table number");
3977 0 : return 0;
3978 : }
3979 :
3980 0 : sal_uInt16 ScDocument::GetCommonWidth( SCCOL nEndCol, SCTAB nTab ) const
3981 : {
3982 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3983 0 : return maTabs[nTab]->GetCommonWidth( nEndCol );
3984 : OSL_FAIL("Wrong table number");
3985 0 : return 0;
3986 : }
3987 :
3988 70029 : sal_uInt16 ScDocument::GetOriginalHeight( SCROW nRow, SCTAB nTab ) const
3989 : {
3990 70029 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3991 70029 : return maTabs[nTab]->GetOriginalHeight( nRow );
3992 : OSL_FAIL("Wrong table number");
3993 0 : return 0;
3994 : }
3995 :
3996 234435457 : sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const
3997 : {
3998 234435457 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
3999 234435457 : return maTabs[nTab]->GetRowHeight( nRow, NULL, NULL, bHiddenAsZero );
4000 : OSL_FAIL("Wrong sheet number");
4001 0 : return 0;
4002 : }
4003 :
4004 77882 : sal_uInt16 ScDocument::GetRowHeight( SCROW nRow, SCTAB nTab, SCROW* pStartRow, SCROW* pEndRow, bool bHiddenAsZero ) const
4005 : {
4006 77882 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4007 77882 : return maTabs[nTab]->GetRowHeight( nRow, pStartRow, pEndRow, bHiddenAsZero );
4008 : OSL_FAIL("Wrong sheet number");
4009 0 : return 0;
4010 : }
4011 :
4012 11362 : sal_uLong ScDocument::GetRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHiddenAsZero ) const
4013 : {
4014 11362 : if (nStartRow == nEndRow)
4015 3791 : return GetRowHeight( nStartRow, nTab, bHiddenAsZero ); // faster for a single row
4016 :
4017 : // check bounds because this method replaces former for(i=start;i<=end;++i) loops
4018 7571 : if (nStartRow > nEndRow)
4019 2171 : return 0;
4020 :
4021 5400 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4022 5400 : return maTabs[nTab]->GetRowHeight( nStartRow, nEndRow, bHiddenAsZero );
4023 :
4024 : OSL_FAIL("wrong sheet number");
4025 0 : return 0;
4026 : }
4027 :
4028 3560 : SCROW ScDocument::GetRowForHeight( SCTAB nTab, sal_uLong nHeight ) const
4029 : {
4030 3560 : return maTabs[nTab]->GetRowForHeight(nHeight);
4031 : }
4032 :
4033 54900 : sal_uLong ScDocument::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow,
4034 : SCTAB nTab, double fScale ) const
4035 : {
4036 : // faster for a single row
4037 54900 : if (nStartRow == nEndRow)
4038 104 : return (sal_uLong) (GetRowHeight( nStartRow, nTab) * fScale);
4039 :
4040 : // check bounds because this method replaces former for(i=start;i<=end;++i) loops
4041 54796 : if (nStartRow > nEndRow)
4042 54793 : return 0;
4043 :
4044 3 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4045 3 : return maTabs[nTab]->GetScaledRowHeight( nStartRow, nEndRow, fScale);
4046 :
4047 : OSL_FAIL("wrong sheet number");
4048 0 : return 0;
4049 : }
4050 :
4051 70 : SCROW ScDocument::GetHiddenRowCount( SCROW nRow, SCTAB nTab ) const
4052 : {
4053 70 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4054 70 : return maTabs[nTab]->GetHiddenRowCount( nRow );
4055 : OSL_FAIL("wrong table number");
4056 0 : return 0;
4057 : }
4058 :
4059 1653 : sal_uLong ScDocument::GetColOffset( SCCOL nCol, SCTAB nTab, bool bHiddenAsZero ) const
4060 : {
4061 1653 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4062 1653 : return maTabs[nTab]->GetColOffset( nCol, bHiddenAsZero );
4063 : OSL_FAIL("wrong table number");
4064 0 : return 0;
4065 : }
4066 :
4067 1653 : sal_uLong ScDocument::GetRowOffset( SCROW nRow, SCTAB nTab, bool bHiddenAsZero ) const
4068 : {
4069 1653 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4070 1653 : return maTabs[nTab]->GetRowOffset( nRow, bHiddenAsZero );
4071 : OSL_FAIL("wrong table number");
4072 0 : return 0;
4073 : }
4074 :
4075 98 : sal_uInt16 ScDocument::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, OutputDevice* pDev,
4076 : double nPPTX, double nPPTY,
4077 : const Fraction& rZoomX, const Fraction& rZoomY,
4078 : bool bFormula, const ScMarkData* pMarkData,
4079 : const ScColWidthParam* pParam )
4080 : {
4081 98 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4082 98 : return maTabs[nTab]->GetOptimalColWidth( nCol, pDev, nPPTX, nPPTY,
4083 196 : rZoomX, rZoomY, bFormula, pMarkData, pParam );
4084 : OSL_FAIL("wrong table number");
4085 0 : return 0;
4086 : }
4087 :
4088 0 : long ScDocument::GetNeededSize( SCCOL nCol, SCROW nRow, SCTAB nTab,
4089 : OutputDevice* pDev,
4090 : double nPPTX, double nPPTY,
4091 : const Fraction& rZoomX, const Fraction& rZoomY,
4092 : bool bWidth, bool bTotalSize )
4093 : {
4094 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4095 0 : return maTabs[nTab]->GetNeededSize
4096 0 : ( nCol, nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, bTotalSize );
4097 : OSL_FAIL("wrong table number");
4098 0 : return 0;
4099 : }
4100 :
4101 804 : bool ScDocument::SetOptimalHeight( sc::RowHeightContext& rCxt, SCROW nStartRow, SCROW nEndRow, SCTAB nTab )
4102 : {
4103 804 : ScTable* pTab = FetchTable(nTab);
4104 804 : if (!pTab)
4105 4 : return false;
4106 :
4107 800 : return pTab->SetOptimalHeight(rCxt, nStartRow, nEndRow);
4108 : }
4109 :
4110 5 : void ScDocument::UpdateAllRowHeights( sc::RowHeightContext& rCxt, const ScMarkData* pTabMark )
4111 : {
4112 : // one progress across all (selected) sheets
4113 :
4114 5 : sal_uLong nCellCount = 0;
4115 13 : for ( SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()); nTab++ )
4116 8 : if ( maTabs[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) )
4117 8 : nCellCount += maTabs[nTab]->GetWeightedCount();
4118 :
4119 5 : ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nCellCount );
4120 :
4121 5 : sal_uLong nProgressStart = 0;
4122 13 : for ( SCTAB nTab=0; nTab< static_cast<SCTAB>(maTabs.size()); nTab++ )
4123 8 : if ( maTabs[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) )
4124 : {
4125 8 : maTabs[nTab]->SetOptimalHeightOnly(rCxt, 0, MAXROW, &aProgress, nProgressStart);
4126 8 : maTabs[nTab]->SetDrawPageSize(true, true);
4127 8 : nProgressStart += maTabs[nTab]->GetWeightedCount();
4128 5 : }
4129 5 : }
4130 :
4131 : // Column/Row - Flags ----------------------------------------------
4132 :
4133 15973 : void ScDocument::ShowCol(SCCOL nCol, SCTAB nTab, bool bShow)
4134 : {
4135 15973 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4136 15973 : maTabs[nTab]->ShowCol( nCol, bShow );
4137 15973 : }
4138 :
4139 0 : void ScDocument::ShowRow(SCROW nRow, SCTAB nTab, bool bShow)
4140 : {
4141 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4142 0 : maTabs[nTab]->ShowRow( nRow, bShow );
4143 0 : }
4144 :
4145 51 : void ScDocument::ShowRows(SCROW nRow1, SCROW nRow2, SCTAB nTab, bool bShow)
4146 : {
4147 51 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4148 51 : maTabs[nTab]->ShowRows( nRow1, nRow2, bShow );
4149 51 : }
4150 :
4151 0 : void ScDocument::SetRowFlags( SCROW nRow, SCTAB nTab, sal_uInt8 nNewFlags )
4152 : {
4153 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4154 0 : maTabs[nTab]->SetRowFlags( nRow, nNewFlags );
4155 0 : }
4156 :
4157 11 : void ScDocument::SetRowFlags( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, sal_uInt8 nNewFlags )
4158 : {
4159 11 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4160 11 : maTabs[nTab]->SetRowFlags( nStartRow, nEndRow, nNewFlags );
4161 11 : }
4162 :
4163 0 : sal_uInt8 ScDocument::GetColFlags( SCCOL nCol, SCTAB nTab ) const
4164 : {
4165 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4166 0 : return maTabs[nTab]->GetColFlags( nCol );
4167 : OSL_FAIL("wrong table number");
4168 0 : return 0;
4169 : }
4170 :
4171 2529 : sal_uInt8 ScDocument::GetRowFlags( SCROW nRow, SCTAB nTab ) const
4172 : {
4173 2529 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4174 2529 : return maTabs[nTab]->GetRowFlags( nRow );
4175 : OSL_FAIL("wrong table number");
4176 0 : return 0;
4177 : }
4178 :
4179 129 : void ScDocument::GetAllRowBreaks(set<SCROW>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const
4180 : {
4181 129 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4182 129 : return;
4183 129 : maTabs[nTab]->GetAllRowBreaks(rBreaks, bPage, bManual);
4184 : }
4185 :
4186 129 : void ScDocument::GetAllColBreaks(set<SCCOL>& rBreaks, SCTAB nTab, bool bPage, bool bManual) const
4187 : {
4188 129 : if (!ValidTab(nTab) || !maTabs[nTab])
4189 129 : return;
4190 :
4191 129 : maTabs[nTab]->GetAllColBreaks(rBreaks, bPage, bManual);
4192 : }
4193 :
4194 23083 : ScBreakType ScDocument::HasRowBreak(SCROW nRow, SCTAB nTab) const
4195 : {
4196 23083 : ScBreakType nType = BREAK_NONE;
4197 23083 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow))
4198 0 : return nType;
4199 :
4200 23083 : if (maTabs[nTab]->HasRowPageBreak(nRow))
4201 4 : nType |= BREAK_PAGE;
4202 :
4203 23083 : if (maTabs[nTab]->HasRowManualBreak(nRow))
4204 3 : nType |= BREAK_MANUAL;
4205 :
4206 23083 : return nType;
4207 : }
4208 :
4209 49623 : ScBreakType ScDocument::HasColBreak(SCCOL nCol, SCTAB nTab) const
4210 : {
4211 49623 : ScBreakType nType = BREAK_NONE;
4212 49623 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol))
4213 0 : return nType;
4214 :
4215 49623 : if (maTabs[nTab]->HasColPageBreak(nCol))
4216 44 : nType |= BREAK_PAGE;
4217 :
4218 49623 : if (maTabs[nTab]->HasColManualBreak(nCol))
4219 11 : nType |= BREAK_MANUAL;
4220 :
4221 49623 : return nType;
4222 : }
4223 :
4224 1 : void ScDocument::SetRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual)
4225 : {
4226 1 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow))
4227 1 : return;
4228 :
4229 1 : maTabs[nTab]->SetRowBreak(nRow, bPage, bManual);
4230 : }
4231 :
4232 1 : void ScDocument::SetColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual)
4233 : {
4234 1 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol))
4235 1 : return;
4236 :
4237 1 : maTabs[nTab]->SetColBreak(nCol, bPage, bManual);
4238 : }
4239 :
4240 1 : void ScDocument::RemoveRowBreak(SCROW nRow, SCTAB nTab, bool bPage, bool bManual)
4241 : {
4242 1 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidRow(nRow))
4243 1 : return;
4244 :
4245 1 : maTabs[nTab]->RemoveRowBreak(nRow, bPage, bManual);
4246 : }
4247 :
4248 1 : void ScDocument::RemoveColBreak(SCCOL nCol, SCTAB nTab, bool bPage, bool bManual)
4249 : {
4250 1 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab] || !ValidCol(nCol))
4251 1 : return;
4252 :
4253 1 : maTabs[nTab]->RemoveColBreak(nCol, bPage, bManual);
4254 : }
4255 :
4256 6 : Sequence<TablePageBreakData> ScDocument::GetRowBreakData(SCTAB nTab) const
4257 : {
4258 6 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4259 0 : return Sequence<TablePageBreakData>();
4260 :
4261 6 : return maTabs[nTab]->GetRowBreakData();
4262 : }
4263 :
4264 18927638 : bool ScDocument::RowHidden(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) const
4265 : {
4266 18927638 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4267 0 : return false;
4268 :
4269 18927638 : return maTabs[nTab]->RowHidden(nRow, pFirstRow, pLastRow);
4270 : }
4271 :
4272 3 : bool ScDocument::HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4273 : {
4274 3 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4275 0 : return false;
4276 :
4277 3 : return maTabs[nTab]->HasHiddenRows(nStartRow, nEndRow);
4278 : }
4279 :
4280 302322 : bool ScDocument::ColHidden(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) const
4281 : {
4282 302322 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4283 : {
4284 0 : if (pFirstCol)
4285 0 : *pFirstCol = nCol;
4286 0 : if (pLastCol)
4287 0 : *pLastCol = nCol;
4288 0 : return false;
4289 : }
4290 :
4291 302322 : return maTabs[nTab]->ColHidden(nCol, pFirstCol, pLastCol);
4292 : }
4293 :
4294 44 : void ScDocument::SetRowHidden(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bHidden)
4295 : {
4296 44 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4297 44 : return;
4298 :
4299 44 : maTabs[nTab]->SetRowHidden(nStartRow, nEndRow, bHidden);
4300 : }
4301 :
4302 1 : void ScDocument::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, SCTAB nTab, bool bHidden)
4303 : {
4304 1 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4305 1 : return;
4306 :
4307 1 : maTabs[nTab]->SetColHidden(nStartCol, nEndCol, bHidden);
4308 : }
4309 :
4310 174 : SCROW ScDocument::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4311 : {
4312 174 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4313 0 : return ::std::numeric_limits<SCROW>::max();
4314 :
4315 174 : return maTabs[nTab]->FirstVisibleRow(nStartRow, nEndRow);
4316 : }
4317 :
4318 6 : SCROW ScDocument::LastVisibleRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4319 : {
4320 6 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4321 0 : return ::std::numeric_limits<SCROW>::max();
4322 :
4323 6 : return maTabs[nTab]->LastVisibleRow(nStartRow, nEndRow);
4324 : }
4325 :
4326 38 : SCROW ScDocument::CountVisibleRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4327 : {
4328 38 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4329 0 : return 0;
4330 :
4331 38 : return maTabs[nTab]->CountVisibleRows(nStartRow, nEndRow);
4332 : }
4333 :
4334 6291809 : bool ScDocument::RowFiltered(SCROW nRow, SCTAB nTab, SCROW* pFirstRow, SCROW* pLastRow) const
4335 : {
4336 6291809 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4337 0 : return false;
4338 :
4339 6291809 : return maTabs[nTab]->RowFiltered(nRow, pFirstRow, pLastRow);
4340 : }
4341 :
4342 2051 : bool ScDocument::HasFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4343 : {
4344 2051 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4345 0 : return false;
4346 :
4347 2051 : return maTabs[nTab]->HasFilteredRows(nStartRow, nEndRow);
4348 : }
4349 :
4350 21 : bool ScDocument::ColFiltered(SCCOL nCol, SCTAB nTab, SCCOL* pFirstCol, SCCOL* pLastCol) const
4351 : {
4352 21 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4353 0 : return false;
4354 :
4355 21 : return maTabs[nTab]->ColFiltered(nCol, pFirstCol, pLastCol);
4356 : }
4357 :
4358 39 : void ScDocument::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bFiltered)
4359 : {
4360 39 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4361 39 : return;
4362 :
4363 39 : maTabs[nTab]->SetRowFiltered(nStartRow, nEndRow, bFiltered);
4364 : }
4365 :
4366 38 : SCROW ScDocument::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4367 : {
4368 38 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4369 0 : return ::std::numeric_limits<SCROW>::max();
4370 :
4371 38 : return maTabs[nTab]->FirstNonFilteredRow(nStartRow, nEndRow);
4372 : }
4373 :
4374 0 : SCROW ScDocument::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4375 : {
4376 0 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4377 0 : return ::std::numeric_limits<SCROW>::max();
4378 :
4379 0 : return maTabs[nTab]->LastNonFilteredRow(nStartRow, nEndRow);
4380 : }
4381 :
4382 74 : SCROW ScDocument::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
4383 : {
4384 74 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4385 0 : return 0;
4386 :
4387 74 : return maTabs[nTab]->CountNonFilteredRows(nStartRow, nEndRow);
4388 : }
4389 :
4390 7 : bool ScDocument::IsManualRowHeight(SCROW nRow, SCTAB nTab) const
4391 : {
4392 7 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4393 0 : return false;
4394 :
4395 7 : return maTabs[nTab]->IsManualRowHeight(nRow);
4396 : }
4397 :
4398 33 : void ScDocument::SyncColRowFlags()
4399 : {
4400 33 : TableContainer::iterator it = maTabs.begin();
4401 76 : for (; it != maTabs.end(); ++it)
4402 : {
4403 43 : if (*it)
4404 43 : (*it)->SyncColRowFlags();
4405 : }
4406 33 : }
4407 :
4408 129 : SCROW ScDocument::GetLastFlaggedRow( SCTAB nTab ) const
4409 : {
4410 129 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4411 129 : return maTabs[nTab]->GetLastFlaggedRow();
4412 0 : return 0;
4413 : }
4414 :
4415 33 : SCCOL ScDocument::GetLastChangedCol( SCTAB nTab ) const
4416 : {
4417 33 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4418 33 : return maTabs[nTab]->GetLastChangedCol();
4419 0 : return 0;
4420 : }
4421 :
4422 33 : SCROW ScDocument::GetLastChangedRow( SCTAB nTab ) const
4423 : {
4424 33 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4425 33 : return maTabs[nTab]->GetLastChangedRow();
4426 0 : return 0;
4427 : }
4428 :
4429 40 : SCCOL ScDocument::GetNextDifferentChangedCol( SCTAB nTab, SCCOL nStart) const
4430 : {
4431 40 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4432 : {
4433 40 : sal_uInt8 nStartFlags = maTabs[nTab]->GetColFlags(nStart);
4434 40 : sal_uInt16 nStartWidth = maTabs[nTab]->GetOriginalWidth(nStart);
4435 33792 : for (SCCOL nCol = nStart + 1; nCol <= MAXCOL; nCol++)
4436 : {
4437 101277 : if (((nStartFlags & CR_MANUALBREAK) != (maTabs[nTab]->GetColFlags(nCol) & CR_MANUALBREAK)) ||
4438 67511 : (nStartWidth != maTabs[nTab]->GetOriginalWidth(nCol)) ||
4439 33752 : ((nStartFlags & CR_HIDDEN) != (maTabs[nTab]->GetColFlags(nCol) & CR_HIDDEN)) )
4440 7 : return nCol;
4441 : }
4442 33 : return MAXCOL+1;
4443 : }
4444 0 : return 0;
4445 : }
4446 :
4447 62 : SCROW ScDocument::GetNextDifferentChangedRow( SCTAB nTab, SCROW nStart, bool bCareManualSize) const
4448 : {
4449 62 : if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size()) || !maTabs[nTab])
4450 0 : return 0;
4451 :
4452 62 : const ScBitMaskCompressedArray<SCROW, sal_uInt8>* pRowFlagsArray = maTabs[nTab]->GetRowFlagsArray();
4453 62 : if (!pRowFlagsArray)
4454 0 : return 0;
4455 :
4456 62 : if (!maTabs[nTab]->mpRowHeights || !maTabs[nTab]->mpHiddenRows)
4457 0 : return 0;
4458 :
4459 : size_t nIndex; // ignored
4460 : SCROW nFlagsEndRow;
4461 : SCROW nHiddenEndRow;
4462 : SCROW nHeightEndRow;
4463 : sal_uInt8 nFlags;
4464 : bool bHidden;
4465 : sal_uInt16 nHeight;
4466 62 : sal_uInt8 nStartFlags = nFlags = pRowFlagsArray->GetValue( nStart, nIndex, nFlagsEndRow);
4467 62 : bool bStartHidden = bHidden = maTabs[nTab]->RowHidden( nStart, NULL, &nHiddenEndRow);
4468 62 : sal_uInt16 nStartHeight = nHeight = maTabs[nTab]->GetRowHeight( nStart, NULL, &nHeightEndRow, false);
4469 : SCROW nRow;
4470 124 : while ((nRow = std::min( nHiddenEndRow, std::min( nFlagsEndRow, nHeightEndRow)) + 1) <= MAXROW)
4471 : {
4472 29 : if (nFlagsEndRow < nRow)
4473 0 : nFlags = pRowFlagsArray->GetValue( nRow, nIndex, nFlagsEndRow);
4474 29 : if (nHiddenEndRow < nRow)
4475 0 : bHidden = maTabs[nTab]->RowHidden( nRow, NULL, &nHiddenEndRow);
4476 29 : if (nHeightEndRow < nRow)
4477 29 : nHeight = maTabs[nTab]->GetRowHeight( nRow, NULL, &nHeightEndRow, false);
4478 :
4479 58 : if (((nStartFlags & CR_MANUALBREAK) != (nFlags & CR_MANUALBREAK)) ||
4480 58 : ((nStartFlags & CR_MANUALSIZE) != (nFlags & CR_MANUALSIZE)) ||
4481 29 : (bStartHidden != bHidden) ||
4482 29 : (bCareManualSize && (nStartFlags & CR_MANUALSIZE) && (nStartHeight != nHeight)) ||
4483 58 : (!bCareManualSize && ((nStartHeight != nHeight))))
4484 29 : return nRow;
4485 : }
4486 :
4487 33 : return MAXROW+1;
4488 : }
4489 :
4490 4193 : bool ScDocument::GetColDefault( SCTAB nTab, SCCOL nCol, SCROW nLastRow, SCROW& nDefault)
4491 : {
4492 4193 : bool bRet(false);
4493 4193 : nDefault = 0;
4494 4193 : ScDocAttrIterator aDocAttrItr(this, nTab, nCol, 0, nCol, nLastRow);
4495 : SCCOL nColumn;
4496 : SCROW nStartRow;
4497 : SCROW nEndRow;
4498 4193 : const ScPatternAttr* pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow);
4499 4193 : if (nEndRow < nLastRow)
4500 : {
4501 34 : ScDefaultAttrSet aSet;
4502 34 : ScDefaultAttrSet::iterator aItr = aSet.end();
4503 173 : while (pAttr)
4504 : {
4505 105 : ScDefaultAttr aAttr(pAttr);
4506 105 : aItr = aSet.find(aAttr);
4507 105 : if (aItr == aSet.end())
4508 : {
4509 92 : aAttr.nCount = static_cast<SCSIZE>(nEndRow - nStartRow + 1);
4510 92 : aAttr.nFirst = nStartRow;
4511 92 : aSet.insert(aAttr);
4512 : }
4513 : else
4514 : {
4515 13 : aAttr.nCount = aItr->nCount + static_cast<SCSIZE>(nEndRow - nStartRow + 1);
4516 13 : aAttr.nFirst = aItr->nFirst;
4517 13 : aSet.erase(aItr);
4518 13 : aSet.insert(aAttr);
4519 : }
4520 105 : pAttr = aDocAttrItr.GetNext(nColumn, nStartRow, nEndRow);
4521 : }
4522 34 : ScDefaultAttrSet::iterator aDefaultItr = aSet.begin();
4523 34 : aItr = aDefaultItr;
4524 34 : ++aItr;
4525 126 : while (aItr != aSet.end())
4526 : {
4527 : // for entries with equal count, use the one with the lowest start row,
4528 : // don't use the random order of pointer comparisons
4529 119 : if ( aItr->nCount > aDefaultItr->nCount ||
4530 68 : ( aItr->nCount == aDefaultItr->nCount && aItr->nFirst < aDefaultItr->nFirst ) )
4531 11 : aDefaultItr = aItr;
4532 58 : ++aItr;
4533 : }
4534 34 : nDefault = aDefaultItr->nFirst;
4535 34 : bRet = true;
4536 : }
4537 : else
4538 4159 : bRet = true;
4539 4193 : return bRet;
4540 : }
4541 :
4542 10483 : void ScDocument::StripHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab )
4543 : {
4544 10483 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4545 10483 : maTabs[nTab]->StripHidden( rX1, rY1, rX2, rY2 );
4546 10483 : }
4547 :
4548 10628 : void ScDocument::ExtendHidden( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2, SCTAB nTab )
4549 : {
4550 10628 : if ( ValidTab(nTab) && maTabs[nTab] )
4551 10628 : maTabs[nTab]->ExtendHidden( rX1, rY1, rX2, rY2 );
4552 10628 : }
4553 :
4554 : // Attribute ----------------------------------------------------------
4555 :
4556 14159 : const SfxPoolItem* ScDocument::GetAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const
4557 : {
4558 14159 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4559 : {
4560 14159 : const SfxPoolItem* pTemp = maTabs[nTab]->GetAttr( nCol, nRow, nWhich );
4561 14159 : if (pTemp)
4562 14159 : return pTemp;
4563 : else
4564 : {
4565 : OSL_FAIL( "Attribut Null" );
4566 : }
4567 : }
4568 0 : return &xPoolHelper->GetDocPool()->GetDefaultItem( nWhich );
4569 : }
4570 :
4571 1376 : const SfxPoolItem* ScDocument::GetAttr( const ScAddress& rPos, sal_uInt16 nWhich ) const
4572 : {
4573 1376 : return GetAttr(rPos.Col(), rPos.Row(), rPos.Tab(), nWhich);
4574 : }
4575 :
4576 20737 : const ScPatternAttr* ScDocument::GetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
4577 : {
4578 20737 : if (TableExists(nTab))
4579 20737 : return maTabs[nTab]->GetPattern( nCol, nRow );
4580 0 : return NULL;
4581 : }
4582 :
4583 24 : const ScPatternAttr* ScDocument::GetPattern( const ScAddress& rPos ) const
4584 : {
4585 24 : if (TableExists(rPos.Tab()))
4586 24 : return maTabs[rPos.Tab()]->GetPattern(rPos.Col(), rPos.Row());
4587 :
4588 0 : return NULL;
4589 : }
4590 :
4591 109824 : const ScPatternAttr* ScDocument::GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) const
4592 : {
4593 109824 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4594 109824 : return maTabs[nTab]->GetMostUsedPattern( nCol, nStartRow, nEndRow );
4595 0 : return NULL;
4596 : }
4597 :
4598 2874 : void ScDocument::ApplyAttr( SCCOL nCol, SCROW nRow, SCTAB nTab, const SfxPoolItem& rAttr )
4599 : {
4600 2874 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4601 2874 : maTabs[nTab]->ApplyAttr( nCol, nRow, rAttr );
4602 2874 : }
4603 :
4604 12 : void ScDocument::ApplyPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr )
4605 : {
4606 12 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4607 12 : maTabs[nTab]->ApplyPattern( nCol, nRow, rAttr );
4608 12 : }
4609 :
4610 1780 : void ScDocument::ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow,
4611 : SCCOL nEndCol, SCROW nEndRow,
4612 : const ScMarkData& rMark,
4613 : const ScPatternAttr& rAttr,
4614 : ScEditDataArray* pDataArray )
4615 : {
4616 1780 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4617 1780 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4618 3560 : for (; itr != itrEnd && *itr < nMax; ++itr)
4619 1780 : if (maTabs[*itr])
4620 1780 : maTabs[*itr]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr, pDataArray );
4621 1780 : }
4622 :
4623 248 : void ScDocument::ApplyPatternAreaTab( SCCOL nStartCol, SCROW nStartRow,
4624 : SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr& rAttr )
4625 : {
4626 248 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4627 248 : if (maTabs[nTab])
4628 248 : maTabs[nTab]->ApplyPatternArea( nStartCol, nStartRow, nEndCol, nEndRow, rAttr );
4629 248 : }
4630 :
4631 0 : void ScDocument::ApplyPatternIfNumberformatIncompatible( const ScRange& rRange,
4632 : const ScMarkData& rMark, const ScPatternAttr& rPattern, short nNewType )
4633 : {
4634 0 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4635 0 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4636 0 : for (; itr != itrEnd && *itr < nMax; ++itr)
4637 0 : if (maTabs[*itr])
4638 0 : maTabs[*itr]->ApplyPatternIfNumberformatIncompatible( rRange, rPattern, nNewType );
4639 0 : }
4640 :
4641 182 : void ScDocument::AddCondFormatData( const ScRangeList& rRange, SCTAB nTab, sal_uInt32 nIndex )
4642 : {
4643 182 : if(!(static_cast<size_t>(nTab) < maTabs.size()))
4644 0 : return;
4645 :
4646 182 : if(!maTabs[nTab])
4647 0 : return;
4648 :
4649 182 : maTabs[nTab]->AddCondFormatData(rRange, nIndex);
4650 : }
4651 :
4652 10 : void ScDocument::RemoveCondFormatData( const ScRangeList& rRange, SCTAB nTab, sal_uInt32 nIndex )
4653 : {
4654 10 : if(!(static_cast<size_t>(nTab) < maTabs.size()))
4655 0 : return;
4656 :
4657 10 : if(!maTabs[nTab])
4658 0 : return;
4659 :
4660 10 : maTabs[nTab]->RemoveCondFormatData(rRange, nIndex);
4661 : }
4662 :
4663 0 : void ScDocument::ApplyStyle( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScStyleSheet& rStyle)
4664 : {
4665 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4666 0 : if (maTabs[nTab])
4667 0 : maTabs[nTab]->ApplyStyle( nCol, nRow, rStyle );
4668 0 : }
4669 :
4670 880 : void ScDocument::ApplyStyleArea( SCCOL nStartCol, SCROW nStartRow,
4671 : SCCOL nEndCol, SCROW nEndRow,
4672 : const ScMarkData& rMark,
4673 : const ScStyleSheet& rStyle)
4674 : {
4675 880 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4676 880 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4677 1760 : for (; itr != itrEnd && *itr < nMax; ++itr)
4678 880 : if (maTabs[*itr])
4679 880 : maTabs[*itr]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
4680 880 : }
4681 :
4682 1295 : void ScDocument::ApplyStyleAreaTab( SCCOL nStartCol, SCROW nStartRow,
4683 : SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet& rStyle)
4684 : {
4685 1295 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4686 1295 : if (maTabs[nTab])
4687 1295 : maTabs[nTab]->ApplyStyleArea( nStartCol, nStartRow, nEndCol, nEndRow, rStyle );
4688 1295 : }
4689 :
4690 1167 : void ScDocument::ApplySelectionStyle(const ScStyleSheet& rStyle, const ScMarkData& rMark)
4691 : {
4692 : // ApplySelectionStyle needs multi mark
4693 1167 : if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
4694 : {
4695 880 : ScRange aRange;
4696 880 : rMark.GetMarkArea( aRange );
4697 880 : ApplyStyleArea( aRange.aStart.Col(), aRange.aStart.Row(),
4698 1760 : aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rStyle );
4699 : }
4700 : else
4701 : {
4702 287 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4703 287 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4704 574 : for (; itr != itrEnd && *itr < nMax; ++itr)
4705 287 : if ( maTabs[*itr] )
4706 287 : maTabs[*itr]->ApplySelectionStyle( rStyle, rMark );
4707 : }
4708 1167 : }
4709 :
4710 0 : void ScDocument::ApplySelectionLineStyle( const ScMarkData& rMark,
4711 : const SvxBorderLine* pLine, bool bColorOnly )
4712 : {
4713 0 : if ( bColorOnly && !pLine )
4714 0 : return;
4715 :
4716 0 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4717 0 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4718 0 : for (; itr != itrEnd && *itr < nMax; ++itr)
4719 0 : if (maTabs[*itr])
4720 0 : maTabs[*itr]->ApplySelectionLineStyle( rMark, pLine, bColorOnly );
4721 : }
4722 :
4723 92 : const ScStyleSheet* ScDocument::GetStyle( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
4724 : {
4725 92 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
4726 92 : return maTabs[nTab]->GetStyle(nCol, nRow);
4727 : else
4728 0 : return NULL;
4729 : }
4730 :
4731 216 : const ScStyleSheet* ScDocument::GetSelectionStyle( const ScMarkData& rMark ) const
4732 : {
4733 216 : bool bEqual = true;
4734 : bool bFound;
4735 :
4736 216 : const ScStyleSheet* pStyle = NULL;
4737 : const ScStyleSheet* pNewStyle;
4738 :
4739 216 : if ( rMark.IsMultiMarked() )
4740 : {
4741 22 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4742 22 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4743 44 : for (; itr != itrEnd && *itr < nMax; ++itr)
4744 22 : if (maTabs[*itr])
4745 : {
4746 22 : pNewStyle = maTabs[*itr]->GetSelectionStyle( rMark, bFound );
4747 22 : if (bFound)
4748 : {
4749 22 : if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
4750 0 : bEqual = false; // different
4751 22 : pStyle = pNewStyle;
4752 : }
4753 : }
4754 : }
4755 216 : if ( rMark.IsMarked() )
4756 : {
4757 194 : ScRange aRange;
4758 194 : rMark.GetMarkArea( aRange );
4759 388 : for (SCTAB i=aRange.aStart.Tab(); i<=aRange.aEnd.Tab() && bEqual && i < static_cast<SCTAB>(maTabs.size()); i++)
4760 194 : if (maTabs[i] && rMark.GetTableSelect(i))
4761 : {
4762 194 : pNewStyle = maTabs[i]->GetAreaStyle( bFound,
4763 194 : aRange.aStart.Col(), aRange.aStart.Row(),
4764 582 : aRange.aEnd.Col(), aRange.aEnd.Row() );
4765 194 : if (bFound)
4766 : {
4767 194 : if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
4768 0 : bEqual = false; // different
4769 194 : pStyle = pNewStyle;
4770 : }
4771 : }
4772 : }
4773 :
4774 216 : return bEqual ? pStyle : NULL;
4775 : }
4776 :
4777 6780 : void ScDocument::StyleSheetChanged( const SfxStyleSheetBase* pStyleSheet, bool bRemoved,
4778 : OutputDevice* pDev,
4779 : double nPPTX, double nPPTY,
4780 : const Fraction& rZoomX, const Fraction& rZoomY )
4781 : {
4782 6780 : TableContainer::iterator it = maTabs.begin();
4783 13560 : for (; it != maTabs.end(); ++it)
4784 6780 : if (*it)
4785 6780 : (*it)->StyleSheetChanged
4786 13560 : ( pStyleSheet, bRemoved, pDev, nPPTX, nPPTY, rZoomX, rZoomY );
4787 :
4788 6780 : if ( pStyleSheet && pStyleSheet->GetName() == ScGlobal::GetRscString(STR_STYLENAME_STANDARD) )
4789 : {
4790 : // update attributes for all note objects
4791 2309 : ScDetectiveFunc::UpdateAllComments( *this );
4792 : }
4793 6780 : }
4794 :
4795 0 : bool ScDocument::IsStyleSheetUsed( const ScStyleSheet& rStyle, bool bGatherAllStyles ) const
4796 : {
4797 0 : if ( bStyleSheetUsageInvalid || rStyle.GetUsage() == ScStyleSheet::UNKNOWN )
4798 : {
4799 0 : if ( bGatherAllStyles )
4800 : {
4801 0 : SfxStyleSheetIterator aIter( xPoolHelper->GetStylePool(),
4802 0 : SFX_STYLE_FAMILY_PARA );
4803 0 : for ( const SfxStyleSheetBase* pStyle = aIter.First(); pStyle;
4804 : pStyle = aIter.Next() )
4805 : {
4806 0 : const ScStyleSheet* pScStyle = PTR_CAST( ScStyleSheet, pStyle );
4807 0 : if ( pScStyle )
4808 0 : pScStyle->SetUsage( ScStyleSheet::NOTUSED );
4809 0 : }
4810 : }
4811 :
4812 0 : bool bIsUsed = false;
4813 :
4814 0 : TableContainer::const_iterator it = maTabs.begin();
4815 0 : for (; it != maTabs.end(); ++it)
4816 0 : if (*it)
4817 : {
4818 0 : if ( (*it)->IsStyleSheetUsed( rStyle, bGatherAllStyles ) )
4819 : {
4820 0 : if ( !bGatherAllStyles )
4821 0 : return true;
4822 0 : bIsUsed = true;
4823 : }
4824 : }
4825 :
4826 0 : if ( bGatherAllStyles )
4827 0 : bStyleSheetUsageInvalid = false;
4828 :
4829 0 : return bIsUsed;
4830 : }
4831 :
4832 0 : return rStyle.GetUsage() == ScStyleSheet::USED;
4833 : }
4834 :
4835 1219 : bool ScDocument::ApplyFlagsTab( SCCOL nStartCol, SCROW nStartRow,
4836 : SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags )
4837 : {
4838 1219 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4839 1218 : if (maTabs[nTab])
4840 1218 : return maTabs[nTab]->ApplyFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
4841 :
4842 : OSL_FAIL("ApplyFlags: wrong table");
4843 1 : return false;
4844 : }
4845 :
4846 354 : bool ScDocument::RemoveFlagsTab( SCCOL nStartCol, SCROW nStartRow,
4847 : SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, sal_Int16 nFlags )
4848 : {
4849 354 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4850 353 : if (maTabs[nTab])
4851 353 : return maTabs[nTab]->RemoveFlags( nStartCol, nStartRow, nEndCol, nEndRow, nFlags );
4852 :
4853 : OSL_FAIL("RemoveFlags: wrong table");
4854 1 : return false;
4855 : }
4856 :
4857 6 : void ScDocument::SetPattern( SCCOL nCol, SCROW nRow, SCTAB nTab, const ScPatternAttr& rAttr,
4858 : bool bPutToPool )
4859 : {
4860 6 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
4861 6 : if (maTabs[nTab])
4862 6 : maTabs[nTab]->SetPattern( nCol, nRow, rAttr, bPutToPool );
4863 6 : }
4864 :
4865 0 : void ScDocument::SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr,
4866 : bool bPutToPool )
4867 : {
4868 0 : SCTAB nTab = rPos.Tab();
4869 0 : if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
4870 0 : maTabs[nTab]->SetPattern( rPos, rAttr, bPutToPool );
4871 0 : }
4872 :
4873 17060 : ScPatternAttr* ScDocument::CreateSelectionPattern( const ScMarkData& rMark, bool bDeep )
4874 : {
4875 17060 : ScMergePatternState aState;
4876 :
4877 17060 : if ( rMark.IsMultiMarked() ) // multi selection
4878 : {
4879 296 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4880 296 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4881 592 : for (; itr != itrEnd && *itr < nMax; ++itr)
4882 296 : if (maTabs[*itr])
4883 296 : maTabs[*itr]->MergeSelectionPattern( aState, rMark, bDeep );
4884 : }
4885 17060 : if ( rMark.IsMarked() ) // single selection
4886 : {
4887 16764 : ScRange aRange;
4888 16764 : rMark.GetMarkArea(aRange);
4889 16764 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4890 16764 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4891 33528 : for (; itr != itrEnd && *itr < nMax; ++itr)
4892 16764 : if (maTabs[*itr])
4893 16764 : maTabs[*itr]->MergePatternArea( aState,
4894 16764 : aRange.aStart.Col(), aRange.aStart.Row(),
4895 50292 : aRange.aEnd.Col(), aRange.aEnd.Row(), bDeep );
4896 : }
4897 :
4898 : OSL_ENSURE( aState.pItemSet, "SelectionPattern Null" );
4899 17060 : if (aState.pItemSet)
4900 17060 : return new ScPatternAttr( aState.pItemSet );
4901 : else
4902 0 : return new ScPatternAttr( GetPool() ); // empty
4903 : }
4904 :
4905 9668 : const ScPatternAttr* ScDocument::GetSelectionPattern( const ScMarkData& rMark, bool bDeep )
4906 : {
4907 9668 : delete pSelectionAttr;
4908 9668 : pSelectionAttr = CreateSelectionPattern( rMark, bDeep );
4909 9668 : return pSelectionAttr;
4910 : }
4911 :
4912 60 : void ScDocument::GetSelectionFrame( const ScMarkData& rMark,
4913 : SvxBoxItem& rLineOuter,
4914 : SvxBoxInfoItem& rLineInner )
4915 : {
4916 60 : rLineOuter.SetLine(NULL, SvxBoxItemLine::TOP);
4917 60 : rLineOuter.SetLine(NULL, SvxBoxItemLine::BOTTOM);
4918 60 : rLineOuter.SetLine(NULL, SvxBoxItemLine::LEFT);
4919 60 : rLineOuter.SetLine(NULL, SvxBoxItemLine::RIGHT);
4920 60 : rLineOuter.SetDistance(0);
4921 :
4922 60 : rLineInner.SetLine(NULL, SvxBoxInfoItemLine::HORI);
4923 60 : rLineInner.SetLine(NULL, SvxBoxInfoItemLine::VERT);
4924 60 : rLineInner.SetTable(true);
4925 60 : rLineInner.SetDist(true);
4926 60 : rLineInner.SetMinDist(false);
4927 :
4928 60 : ScLineFlags aFlags;
4929 :
4930 60 : if (rMark.IsMarked())
4931 : {
4932 60 : ScRange aRange;
4933 60 : rMark.GetMarkArea(aRange);
4934 60 : rLineInner.EnableHor( aRange.aStart.Row() != aRange.aEnd.Row() );
4935 60 : rLineInner.EnableVer( aRange.aStart.Col() != aRange.aEnd.Col() );
4936 60 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
4937 60 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
4938 120 : for (; itr != itrEnd && *itr < nMax; ++itr)
4939 60 : if (maTabs[*itr])
4940 60 : maTabs[*itr]->MergeBlockFrame( &rLineOuter, &rLineInner, aFlags,
4941 60 : aRange.aStart.Col(), aRange.aStart.Row(),
4942 180 : aRange.aEnd.Col(), aRange.aEnd.Row() );
4943 : }
4944 :
4945 : // Evaluate don't care Status
4946 :
4947 60 : rLineInner.SetValid( SvxBoxInfoItemValidFlags::LEFT, ( aFlags.nLeft != SC_LINE_DONTCARE ) );
4948 60 : rLineInner.SetValid( SvxBoxInfoItemValidFlags::RIGHT, ( aFlags.nRight != SC_LINE_DONTCARE ) );
4949 60 : rLineInner.SetValid( SvxBoxInfoItemValidFlags::TOP, ( aFlags.nTop != SC_LINE_DONTCARE ) );
4950 60 : rLineInner.SetValid( SvxBoxInfoItemValidFlags::BOTTOM, ( aFlags.nBottom != SC_LINE_DONTCARE ) );
4951 60 : rLineInner.SetValid( SvxBoxInfoItemValidFlags::HORI, ( aFlags.nHori != SC_LINE_DONTCARE ) );
4952 60 : rLineInner.SetValid( SvxBoxInfoItemValidFlags::VERT, ( aFlags.nVert != SC_LINE_DONTCARE ) );
4953 60 : }
4954 :
4955 27747 : bool ScDocument::HasAttrib( SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
4956 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt16 nMask ) const
4957 : {
4958 27747 : if ( nMask & HASATTR_ROTATE )
4959 : {
4960 : // Is attribute used in document?
4961 : // (as in fillinfo)
4962 :
4963 18282 : ScDocumentPool* pPool = xPoolHelper->GetDocPool();
4964 :
4965 18282 : bool bAnyItem = false;
4966 18282 : sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE );
4967 46811 : for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++)
4968 : {
4969 29112 : const SfxPoolItem* pItem = pPool->GetItem2( ATTR_ROTATE_VALUE, nItem );
4970 29112 : if ( pItem )
4971 : {
4972 : // 90 or 270 degrees is former SvxOrientationItem - only look for other values
4973 : // (see ScPatternAttr::GetCellOrientation)
4974 28816 : sal_Int32 nAngle = static_cast<const SfxInt32Item*>(pItem)->GetValue();
4975 28816 : if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 )
4976 : {
4977 583 : bAnyItem = true;
4978 583 : break;
4979 : }
4980 : }
4981 : }
4982 18282 : if (!bAnyItem)
4983 17699 : nMask &= ~HASATTR_ROTATE;
4984 : }
4985 :
4986 27747 : if ( nMask & HASATTR_RTL )
4987 : {
4988 : // first check if right-to left is in the pool at all
4989 : // (the same item is used in cell and page format)
4990 :
4991 0 : ScDocumentPool* pPool = xPoolHelper->GetDocPool();
4992 :
4993 0 : bool bHasRtl = false;
4994 0 : sal_uInt32 nDirCount = pPool->GetItemCount2( ATTR_WRITINGDIR );
4995 0 : for (sal_uInt32 nItem=0; nItem<nDirCount; nItem++)
4996 : {
4997 0 : const SfxPoolItem* pItem = pPool->GetItem2( ATTR_WRITINGDIR, nItem );
4998 0 : if ( pItem && static_cast<const SvxFrameDirectionItem*>(pItem)->GetValue() == FRMDIR_HORI_RIGHT_TOP )
4999 : {
5000 0 : bHasRtl = true;
5001 0 : break;
5002 : }
5003 : }
5004 0 : if (!bHasRtl)
5005 0 : nMask &= ~HASATTR_RTL;
5006 : }
5007 :
5008 27747 : if (!nMask)
5009 0 : return false;
5010 :
5011 27747 : bool bFound = false;
5012 55483 : for (SCTAB i=nTab1; i<=nTab2 && !bFound && i < static_cast<SCTAB>(maTabs.size()); i++)
5013 27736 : if (maTabs[i])
5014 : {
5015 27736 : if ( nMask & HASATTR_RTL )
5016 : {
5017 0 : if ( GetEditTextDirection(i) == EE_HTEXTDIR_R2L ) // sheet default
5018 0 : bFound = true;
5019 : }
5020 27736 : if ( nMask & HASATTR_RIGHTORCENTER )
5021 : {
5022 : // On a RTL sheet, don't start to look for the default left value
5023 : // (which is then logically right), instead always assume true.
5024 : // That way, ScAttrArray::HasAttrib doesn't have to handle RTL sheets.
5025 :
5026 7795 : if ( IsLayoutRTL(i) )
5027 0 : bFound = true;
5028 : }
5029 :
5030 27736 : if ( !bFound )
5031 27736 : bFound = maTabs[i]->HasAttrib( nCol1, nRow1, nCol2, nRow2, nMask );
5032 : }
5033 :
5034 27747 : return bFound;
5035 : }
5036 :
5037 8662 : bool ScDocument::HasAttrib( const ScRange& rRange, sal_uInt16 nMask ) const
5038 : {
5039 17324 : return HasAttrib( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aStart.Tab(),
5040 17324 : rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aEnd.Tab(),
5041 43310 : nMask );
5042 : }
5043 :
5044 400 : void ScDocument::FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount,
5045 : SCCOL nX1, SCCOL nX2 ) const
5046 : {
5047 400 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5048 400 : maTabs[nTab]->FindMaxRotCol( pRowInfo, nArrCount, nX1, nX2 );
5049 : else
5050 : {
5051 : OSL_FAIL("FindMaxRotCol: wrong table");
5052 : }
5053 400 : }
5054 :
5055 183 : void ScDocument::GetBorderLines( SCCOL nCol, SCROW nRow, SCTAB nTab,
5056 : const SvxBorderLine** ppLeft, const SvxBorderLine** ppTop,
5057 : const SvxBorderLine** ppRight, const SvxBorderLine** ppBottom ) const
5058 : {
5059 : //TODO: consider page limits for printing !!!!!
5060 :
5061 183 : const SvxBoxItem* pThisAttr = static_cast<const SvxBoxItem*>( GetEffItem( nCol, nRow, nTab, ATTR_BORDER ) );
5062 : OSL_ENSURE(pThisAttr,"where is the attribute?");
5063 :
5064 183 : const SvxBorderLine* pLeftLine = pThisAttr->GetLeft();
5065 183 : const SvxBorderLine* pTopLine = pThisAttr->GetTop();
5066 183 : const SvxBorderLine* pRightLine = pThisAttr->GetRight();
5067 183 : const SvxBorderLine* pBottomLine = pThisAttr->GetBottom();
5068 :
5069 183 : if ( nCol > 0 )
5070 : {
5071 : const SvxBorderLine* pOther = static_cast<const SvxBoxItem*>(
5072 160 : GetEffItem( nCol-1, nRow, nTab, ATTR_BORDER ))->GetRight();
5073 160 : if ( ScHasPriority( pOther, pLeftLine ) )
5074 17 : pLeftLine = pOther;
5075 : }
5076 183 : if ( nRow > 0 )
5077 : {
5078 : const SvxBorderLine* pOther = static_cast<const SvxBoxItem*>(
5079 177 : GetEffItem( nCol, nRow-1, nTab, ATTR_BORDER ))->GetBottom();
5080 177 : if ( ScHasPriority( pOther, pTopLine ) )
5081 16 : pTopLine = pOther;
5082 : }
5083 183 : if ( nCol < MAXCOL )
5084 : {
5085 : const SvxBorderLine* pOther = static_cast<const SvxBoxItem*>(
5086 183 : GetEffItem( nCol+1, nRow, nTab, ATTR_BORDER ))->GetLeft();
5087 183 : if ( ScHasPriority( pOther, pRightLine ) )
5088 18 : pRightLine = pOther;
5089 : }
5090 183 : if ( nRow < MAXROW )
5091 : {
5092 : const SvxBorderLine* pOther = static_cast<const SvxBoxItem*>(
5093 183 : GetEffItem( nCol, nRow+1, nTab, ATTR_BORDER ))->GetTop();
5094 183 : if ( ScHasPriority( pOther, pBottomLine ) )
5095 17 : pBottomLine = pOther;
5096 : }
5097 :
5098 183 : if (ppLeft)
5099 135 : *ppLeft = pLeftLine;
5100 183 : if (ppTop)
5101 183 : *ppTop = pTopLine;
5102 183 : if (ppRight)
5103 135 : *ppRight = pRightLine;
5104 183 : if (ppBottom)
5105 135 : *ppBottom = pBottomLine;
5106 183 : }
5107 :
5108 138 : bool ScDocument::IsBlockEmpty( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
5109 : SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes ) const
5110 : {
5111 138 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
5112 138 : if (maTabs[nTab])
5113 138 : return maTabs[nTab]->IsBlockEmpty( nStartCol, nStartRow, nEndCol, nEndRow, bIgnoreNotes );
5114 :
5115 : OSL_FAIL("wrong table number");
5116 0 : return false;
5117 : }
5118 :
5119 0 : void ScDocument::LockTable(SCTAB nTab)
5120 : {
5121 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5122 0 : maTabs[nTab]->LockTable();
5123 : else
5124 : {
5125 : OSL_FAIL("wrong table number");
5126 : }
5127 0 : }
5128 :
5129 0 : void ScDocument::UnlockTable(SCTAB nTab)
5130 : {
5131 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5132 0 : maTabs[nTab]->UnlockTable();
5133 : else
5134 : {
5135 : OSL_FAIL("wrong table number");
5136 : }
5137 0 : }
5138 :
5139 3602 : bool ScDocument::IsBlockEditable( SCTAB nTab, SCCOL nStartCol, SCROW nStartRow,
5140 : SCCOL nEndCol, SCROW nEndRow,
5141 : bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
5142 : {
5143 : // import into read-only document is possible
5144 3602 : if (!bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly())
5145 : {
5146 0 : if ( pOnlyNotBecauseOfMatrix )
5147 0 : *pOnlyNotBecauseOfMatrix = false;
5148 0 : return false;
5149 : }
5150 :
5151 3602 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
5152 3602 : if (maTabs[nTab])
5153 3602 : return maTabs[nTab]->IsBlockEditable( nStartCol, nStartRow, nEndCol,
5154 7204 : nEndRow, pOnlyNotBecauseOfMatrix );
5155 :
5156 : OSL_FAIL("wrong table number");
5157 0 : if ( pOnlyNotBecauseOfMatrix )
5158 0 : *pOnlyNotBecauseOfMatrix = false;
5159 0 : return false;
5160 : }
5161 :
5162 574 : bool ScDocument::IsSelectionEditable( const ScMarkData& rMark,
5163 : bool* pOnlyNotBecauseOfMatrix /* = NULL */ ) const
5164 : {
5165 : // import into read-only document is possible
5166 574 : if ( !bImportingXML && !mbChangeReadOnlyEnabled && pShell && pShell->IsReadOnly() )
5167 : {
5168 0 : if ( pOnlyNotBecauseOfMatrix )
5169 0 : *pOnlyNotBecauseOfMatrix = false;
5170 0 : return false;
5171 : }
5172 :
5173 574 : ScRange aRange;
5174 574 : rMark.GetMarkArea(aRange);
5175 :
5176 574 : bool bOk = true;
5177 574 : bool bMatrix = ( pOnlyNotBecauseOfMatrix != NULL );
5178 574 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5179 574 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5180 1148 : for (; itr != itrEnd && *itr < nMax && (bOk || bMatrix); ++itr)
5181 : {
5182 574 : if ( maTabs[*itr] )
5183 : {
5184 574 : if (rMark.IsMarked())
5185 : {
5186 1539 : if ( !maTabs[*itr]->IsBlockEditable( aRange.aStart.Col(),
5187 513 : aRange.aStart.Row(), aRange.aEnd.Col(),
5188 2052 : aRange.aEnd.Row(), pOnlyNotBecauseOfMatrix ) )
5189 : {
5190 0 : bOk = false;
5191 0 : if ( pOnlyNotBecauseOfMatrix )
5192 0 : bMatrix = *pOnlyNotBecauseOfMatrix;
5193 : }
5194 : }
5195 574 : if (rMark.IsMultiMarked())
5196 : {
5197 61 : if ( !maTabs[*itr]->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix ) )
5198 : {
5199 0 : bOk = false;
5200 0 : if ( pOnlyNotBecauseOfMatrix )
5201 0 : bMatrix = *pOnlyNotBecauseOfMatrix;
5202 : }
5203 : }
5204 : }
5205 : }
5206 :
5207 574 : if ( pOnlyNotBecauseOfMatrix )
5208 574 : *pOnlyNotBecauseOfMatrix = ( !bOk && bMatrix );
5209 :
5210 574 : return bOk;
5211 : }
5212 :
5213 14 : bool ScDocument::HasSelectedBlockMatrixFragment( SCCOL nStartCol, SCROW nStartRow,
5214 : SCCOL nEndCol, SCROW nEndRow,
5215 : const ScMarkData& rMark ) const
5216 : {
5217 14 : bool bOk = true;
5218 14 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5219 14 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5220 28 : for (; itr != itrEnd && *itr < nMax && bOk; ++itr)
5221 14 : if (maTabs[*itr])
5222 14 : if (maTabs[*itr]->HasBlockMatrixFragment( nStartCol, nStartRow, nEndCol, nEndRow ))
5223 0 : bOk = false;
5224 :
5225 14 : return !bOk;
5226 : }
5227 :
5228 20 : bool ScDocument::GetMatrixFormulaRange( const ScAddress& rCellPos, ScRange& rMatrix )
5229 : {
5230 : // if rCell is part of a matrix formula, return its complete range
5231 :
5232 20 : ScFormulaCell* pFCell = GetFormulaCell(rCellPos);
5233 20 : if (!pFCell)
5234 : // not a formula cell. Bail out.
5235 0 : return false;
5236 :
5237 20 : ScAddress aOrigin = rCellPos;
5238 20 : if (!pFCell->GetMatrixOrigin(aOrigin))
5239 : // Failed to get the address of the matrix origin.
5240 4 : return false;
5241 :
5242 16 : if (aOrigin != rCellPos)
5243 : {
5244 13 : pFCell = GetFormulaCell(aOrigin);
5245 13 : if (!pFCell)
5246 : // The matrix origin cell is not a formula cell !? Something is up...
5247 0 : return false;
5248 : }
5249 :
5250 : SCCOL nSizeX;
5251 : SCROW nSizeY;
5252 16 : pFCell->GetMatColsRows(nSizeX, nSizeY);
5253 16 : if (nSizeX <= 0 || nSizeY <= 0)
5254 : {
5255 : // GetMatrixEdge computes also dimensions of the matrix
5256 : // if not already done (may occur if document is loaded
5257 : // from old file format).
5258 : // Needs an "invalid" initialized address.
5259 0 : aOrigin.SetInvalid();
5260 0 : pFCell->GetMatrixEdge(aOrigin);
5261 0 : pFCell->GetMatColsRows(nSizeX, nSizeY);
5262 : }
5263 :
5264 16 : if (nSizeX <= 0 || nSizeY <= 0)
5265 : // Matrix size is still invalid. Give up.
5266 0 : return false;
5267 :
5268 16 : ScAddress aEnd( aOrigin.Col() + nSizeX - 1,
5269 16 : aOrigin.Row() + nSizeY - 1,
5270 48 : aOrigin.Tab() );
5271 :
5272 16 : rMatrix.aStart = aOrigin;
5273 16 : rMatrix.aEnd = aEnd;
5274 :
5275 16 : return true;
5276 : }
5277 :
5278 373 : bool ScDocument::ExtendOverlapped( SCCOL& rStartCol, SCROW& rStartRow,
5279 : SCCOL nEndCol, SCROW nEndRow, SCTAB nTab ) const
5280 : {
5281 373 : bool bFound = false;
5282 373 : if ( ValidColRow(rStartCol,rStartRow) && ValidColRow(nEndCol,nEndRow) && ValidTab(nTab) )
5283 : {
5284 373 : if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5285 : {
5286 : SCCOL nCol;
5287 373 : SCCOL nOldCol = rStartCol;
5288 373 : SCROW nOldRow = rStartRow;
5289 1816 : for (nCol=nOldCol; nCol<=nEndCol; nCol++)
5290 2889 : while (static_cast<const ScMergeFlagAttr*>(GetAttr(nCol,rStartRow,nTab,ATTR_MERGE_FLAG))->
5291 : IsVerOverlapped())
5292 3 : --rStartRow;
5293 :
5294 : //TODO: pass on ?
5295 :
5296 373 : ScAttrArray* pAttrArray = maTabs[nTab]->aCol[nOldCol].pAttrArray;
5297 : SCSIZE nIndex;
5298 373 : pAttrArray->Search( nOldRow, nIndex );
5299 373 : SCROW nAttrPos = nOldRow;
5300 1155 : while (nAttrPos<=nEndRow)
5301 : {
5302 : OSL_ENSURE( nIndex < pAttrArray->nCount, "Wrong index in AttrArray" );
5303 :
5304 818 : if (static_cast<const ScMergeFlagAttr&>(pAttrArray->pData[nIndex].pPattern->
5305 409 : GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped())
5306 : {
5307 5 : SCROW nLoopEndRow = std::min( nEndRow, pAttrArray->pData[nIndex].nRow );
5308 10 : for (SCROW nAttrRow = nAttrPos; nAttrRow <= nLoopEndRow; nAttrRow++)
5309 : {
5310 5 : SCCOL nTempCol = nOldCol;
5311 5 : do
5312 5 : --nTempCol;
5313 5 : while (static_cast<const ScMergeFlagAttr*>(GetAttr(nTempCol,nAttrRow,nTab,ATTR_MERGE_FLAG))
5314 : ->IsHorOverlapped());
5315 5 : if (nTempCol < rStartCol)
5316 5 : rStartCol = nTempCol;
5317 : }
5318 : }
5319 409 : nAttrPos = pAttrArray->pData[nIndex].nRow + 1;
5320 409 : ++nIndex;
5321 : }
5322 : }
5323 : }
5324 : else
5325 : {
5326 : OSL_FAIL("ExtendOverlapped: invalid range");
5327 : }
5328 :
5329 373 : return bFound;
5330 : }
5331 :
5332 34 : bool ScDocument::ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow,
5333 : SCCOL& rEndCol, SCROW& rEndRow,
5334 : const ScMarkData& rMark, bool bRefresh )
5335 : {
5336 : // use all selected sheets from rMark
5337 :
5338 34 : bool bFound = false;
5339 34 : SCCOL nOldEndCol = rEndCol;
5340 34 : SCROW nOldEndRow = rEndRow;
5341 :
5342 34 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5343 34 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5344 68 : for (; itr != itrEnd && *itr < nMax; ++itr)
5345 34 : if ( maTabs[*itr] )
5346 : {
5347 34 : SCCOL nThisEndCol = nOldEndCol;
5348 34 : SCROW nThisEndRow = nOldEndRow;
5349 34 : if ( ExtendMerge( nStartCol, nStartRow, nThisEndCol, nThisEndRow, *itr, bRefresh ) )
5350 0 : bFound = true;
5351 34 : if ( nThisEndCol > rEndCol )
5352 0 : rEndCol = nThisEndCol;
5353 34 : if ( nThisEndRow > rEndRow )
5354 0 : rEndRow = nThisEndRow;
5355 : }
5356 :
5357 34 : return bFound;
5358 : }
5359 :
5360 10424 : bool ScDocument::ExtendMerge( SCCOL nStartCol, SCROW nStartRow,
5361 : SCCOL& rEndCol, SCROW& rEndRow,
5362 : SCTAB nTab, bool bRefresh )
5363 : {
5364 10424 : bool bFound = false;
5365 10424 : if ( ValidColRow(nStartCol,nStartRow) && ValidColRow(rEndCol,rEndRow) && ValidTab(nTab) )
5366 : {
5367 10424 : if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5368 10424 : bFound = maTabs[nTab]->ExtendMerge( nStartCol, nStartRow, rEndCol, rEndRow, bRefresh );
5369 :
5370 10424 : if (bRefresh)
5371 198 : RefreshAutoFilter( nStartCol, nStartRow, rEndCol, rEndRow, nTab );
5372 : }
5373 : else
5374 : {
5375 : OSL_FAIL("ExtendMerge: invalid range");
5376 : }
5377 :
5378 10424 : return bFound;
5379 : }
5380 :
5381 518 : bool ScDocument::ExtendMerge( ScRange& rRange, bool bRefresh )
5382 : {
5383 518 : bool bFound = false;
5384 518 : SCTAB nStartTab = rRange.aStart.Tab();
5385 518 : SCTAB nEndTab = rRange.aEnd.Tab();
5386 518 : SCCOL nEndCol = rRange.aEnd.Col();
5387 518 : SCROW nEndRow = rRange.aEnd.Row();
5388 :
5389 518 : PutInOrder( nStartTab, nEndTab );
5390 1035 : for (SCTAB nTab = nStartTab; nTab <= nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
5391 : {
5392 517 : SCCOL nExtendCol = rRange.aEnd.Col();
5393 517 : SCROW nExtendRow = rRange.aEnd.Row();
5394 1034 : if (ExtendMerge( rRange.aStart.Col(), rRange.aStart.Row(),
5395 : nExtendCol, nExtendRow,
5396 1034 : nTab, bRefresh ) )
5397 : {
5398 23 : bFound = true;
5399 23 : if (nExtendCol > nEndCol) nEndCol = nExtendCol;
5400 23 : if (nExtendRow > nEndRow) nEndRow = nExtendRow;
5401 : }
5402 : }
5403 :
5404 518 : rRange.aEnd.SetCol(nEndCol);
5405 518 : rRange.aEnd.SetRow(nEndRow);
5406 :
5407 518 : return bFound;
5408 : }
5409 :
5410 1 : bool ScDocument::ExtendTotalMerge( ScRange& rRange ) const
5411 : {
5412 : // Extend range to merged cells without including any new non-overlapped cells
5413 1 : bool bRet = false;
5414 1 : ScRange aExt = rRange;
5415 : // ExtendMerge() is non-const, but called withouth refresh.
5416 1 : if (const_cast<ScDocument*>(this)->ExtendMerge( aExt, false))
5417 : {
5418 0 : if ( aExt.aEnd.Row() > rRange.aEnd.Row() )
5419 : {
5420 0 : ScRange aTest = aExt;
5421 0 : aTest.aStart.SetRow( rRange.aEnd.Row() + 1 );
5422 0 : if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
5423 0 : aExt.aEnd.SetRow(rRange.aEnd.Row());
5424 : }
5425 0 : if ( aExt.aEnd.Col() > rRange.aEnd.Col() )
5426 : {
5427 0 : ScRange aTest = aExt;
5428 0 : aTest.aStart.SetCol( rRange.aEnd.Col() + 1 );
5429 0 : if ( HasAttrib( aTest, HASATTR_NOTOVERLAPPED ) )
5430 0 : aExt.aEnd.SetCol(rRange.aEnd.Col());
5431 : }
5432 :
5433 0 : bRet = ( aExt.aEnd != rRange.aEnd );
5434 0 : rRange = aExt;
5435 : }
5436 1 : return bRet;
5437 : }
5438 :
5439 342 : bool ScDocument::ExtendOverlapped( ScRange& rRange ) const
5440 : {
5441 342 : bool bFound = false;
5442 342 : SCTAB nStartTab = rRange.aStart.Tab();
5443 342 : SCTAB nEndTab = rRange.aEnd.Tab();
5444 342 : SCCOL nStartCol = rRange.aStart.Col();
5445 342 : SCROW nStartRow = rRange.aStart.Row();
5446 :
5447 342 : PutInOrder( nStartTab, nEndTab );
5448 684 : for (SCTAB nTab = nStartTab; nTab <= nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++ )
5449 : {
5450 342 : SCCOL nExtendCol = rRange.aStart.Col();
5451 342 : SCROW nExtendRow = rRange.aStart.Row();
5452 : ExtendOverlapped( nExtendCol, nExtendRow,
5453 342 : rRange.aEnd.Col(), rRange.aEnd.Row(), nTab );
5454 342 : if (nExtendCol < nStartCol)
5455 : {
5456 5 : nStartCol = nExtendCol;
5457 5 : bFound = true;
5458 : }
5459 342 : if (nExtendRow < nStartRow)
5460 : {
5461 2 : nStartRow = nExtendRow;
5462 2 : bFound = true;
5463 : }
5464 : }
5465 :
5466 342 : rRange.aStart.SetCol(nStartCol);
5467 342 : rRange.aStart.SetRow(nStartRow);
5468 :
5469 342 : return bFound;
5470 : }
5471 :
5472 235 : bool ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow,
5473 : SCCOL nEndCol, SCROW nEndRow, SCTAB nTab )
5474 : {
5475 : SCTAB nDBTab;
5476 : SCCOL nDBStartCol;
5477 : SCROW nDBStartRow;
5478 : SCCOL nDBEndCol;
5479 : SCROW nDBEndRow;
5480 :
5481 : // Delete Autofilter
5482 :
5483 235 : bool bChange = RemoveFlagsTab( nStartCol,nStartRow, nEndCol,nEndRow, nTab, SC_MF_AUTO );
5484 :
5485 : // Set Autofilter
5486 :
5487 235 : const ScDBData* pData = NULL;
5488 235 : ScDBCollection::NamedDBs& rDBs = pDBCollection->getNamedDBs();
5489 235 : ScDBCollection::NamedDBs::const_iterator itr = rDBs.begin(), itrEnd = rDBs.end();
5490 235 : for (; itr != itrEnd; ++itr)
5491 : {
5492 0 : if (itr->HasAutoFilter())
5493 : {
5494 0 : itr->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
5495 0 : if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow &&
5496 0 : nDBStartCol<=nEndCol && nDBEndCol>=nStartCol )
5497 : {
5498 0 : if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow,
5499 0 : nDBTab, SC_MF_AUTO ))
5500 0 : bChange = true;
5501 : }
5502 : }
5503 : }
5504 235 : if (nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5505 235 : pData = maTabs[nTab]->GetAnonymousDBData();
5506 : else
5507 0 : pData=NULL;
5508 235 : if (pData)
5509 : {
5510 15 : if (pData->HasAutoFilter())
5511 : {
5512 0 : pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow );
5513 0 : if ( nDBTab==nTab && nDBStartRow<=nEndRow && nDBEndRow>=nStartRow &&
5514 0 : nDBStartCol<=nEndCol && nDBEndCol>=nStartCol )
5515 : {
5516 0 : if (ApplyFlagsTab( nDBStartCol,nDBStartRow, nDBEndCol,nDBStartRow,
5517 0 : nDBTab, SC_MF_AUTO ))
5518 0 : bChange = true;
5519 : }
5520 : }
5521 : }
5522 235 : return bChange;
5523 : }
5524 :
5525 219 : void ScDocument::SkipOverlapped( SCCOL& rCol, SCROW& rRow, SCTAB nTab ) const
5526 : {
5527 438 : while (IsHorOverlapped(rCol, rRow, nTab))
5528 0 : --rCol;
5529 438 : while (IsVerOverlapped(rCol, rRow, nTab))
5530 0 : --rRow;
5531 219 : }
5532 :
5533 286 : bool ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
5534 : {
5535 : const ScMergeFlagAttr* pAttr = static_cast<const ScMergeFlagAttr*>(
5536 286 : GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ));
5537 286 : if (pAttr)
5538 286 : return pAttr->IsHorOverlapped();
5539 : else
5540 : {
5541 : OSL_FAIL("Overlapped: Attr==0");
5542 0 : return false;
5543 : }
5544 : }
5545 :
5546 286 : bool ScDocument::IsVerOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
5547 : {
5548 : const ScMergeFlagAttr* pAttr = static_cast<const ScMergeFlagAttr*>(
5549 286 : GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ));
5550 286 : if (pAttr)
5551 286 : return pAttr->IsVerOverlapped();
5552 : else
5553 : {
5554 : OSL_FAIL("Overlapped: Attr==0");
5555 0 : return false;
5556 : }
5557 : }
5558 :
5559 4 : void ScDocument::ApplySelectionFrame( const ScMarkData& rMark,
5560 : const SvxBoxItem* pLineOuter,
5561 : const SvxBoxInfoItem* pLineInner )
5562 : {
5563 4 : ScRangeList aRangeList;
5564 4 : rMark.FillRangeListWithMarks( &aRangeList, false );
5565 4 : size_t nRangeCount = aRangeList.size();
5566 4 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5567 4 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5568 8 : for (; itr != itrEnd && *itr < nMax; ++itr)
5569 : {
5570 4 : if (maTabs[*itr])
5571 : {
5572 8 : for ( size_t j=0; j < nRangeCount; j++ )
5573 : {
5574 4 : ScRange aRange = *aRangeList[ j ];
5575 4 : maTabs[*itr]->ApplyBlockFrame( pLineOuter, pLineInner,
5576 4 : aRange.aStart.Col(), aRange.aStart.Row(),
5577 12 : aRange.aEnd.Col(), aRange.aEnd.Row() );
5578 : }
5579 : }
5580 4 : }
5581 4 : }
5582 :
5583 970 : void ScDocument::ApplyFrameAreaTab( const ScRange& rRange,
5584 : const SvxBoxItem* pLineOuter,
5585 : const SvxBoxInfoItem* pLineInner )
5586 : {
5587 970 : SCTAB nStartTab = rRange.aStart.Tab();
5588 970 : SCTAB nEndTab = rRange.aStart.Tab();
5589 1940 : for (SCTAB nTab=nStartTab; nTab<=nEndTab && nTab < static_cast<SCTAB>(maTabs.size()); nTab++)
5590 970 : if (maTabs[nTab])
5591 970 : maTabs[nTab]->ApplyBlockFrame( pLineOuter, pLineInner,
5592 970 : rRange.aStart.Col(), rRange.aStart.Row(),
5593 2910 : rRange.aEnd.Col(), rRange.aEnd.Row() );
5594 970 : }
5595 :
5596 1986 : void ScDocument::ApplySelectionPattern( const ScPatternAttr& rAttr, const ScMarkData& rMark, ScEditDataArray* pDataArray )
5597 : {
5598 1986 : const SfxItemSet* pSet = &rAttr.GetItemSet();
5599 1986 : bool bSet = false;
5600 : sal_uInt16 i;
5601 45539 : for (i=ATTR_PATTERN_START; i<=ATTR_PATTERN_END && !bSet; i++)
5602 43553 : if (pSet->GetItemState(i) == SfxItemState::SET)
5603 1986 : bSet = true;
5604 :
5605 1986 : if (bSet)
5606 : {
5607 : // ApplySelectionCache needs multi mark
5608 1986 : if ( rMark.IsMarked() && !rMark.IsMultiMarked() )
5609 : {
5610 1780 : ScRange aRange;
5611 1780 : rMark.GetMarkArea( aRange );
5612 1780 : ApplyPatternArea( aRange.aStart.Col(), aRange.aStart.Row(),
5613 3560 : aRange.aEnd.Col(), aRange.aEnd.Row(), rMark, rAttr, pDataArray );
5614 : }
5615 : else
5616 : {
5617 206 : SfxItemPoolCache aCache( xPoolHelper->GetDocPool(), pSet );
5618 206 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5619 206 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5620 412 : for (; itr != itrEnd && *itr < nMax; ++itr)
5621 206 : if (maTabs[*itr])
5622 412 : maTabs[*itr]->ApplySelectionCache( &aCache, rMark, pDataArray );
5623 : }
5624 : }
5625 1986 : }
5626 :
5627 6 : void ScDocument::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
5628 : {
5629 6 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5630 6 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5631 12 : for (; itr != itrEnd && *itr < nMax; ++itr)
5632 6 : if (maTabs[*itr])
5633 6 : maTabs[*itr]->ChangeSelectionIndent( bIncrement, rMark );
5634 6 : }
5635 :
5636 0 : void ScDocument::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark )
5637 : {
5638 0 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5639 0 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5640 0 : for (; itr != itrEnd && *itr < nMax; ++itr)
5641 0 : if (maTabs[*itr])
5642 0 : maTabs[*itr]->ClearSelectionItems( pWhich, rMark );
5643 0 : }
5644 :
5645 93 : void ScDocument::DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& rMark, bool bBroadcast )
5646 : {
5647 93 : SCTAB nMax = static_cast<SCTAB>(maTabs.size());
5648 93 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
5649 186 : for (; itr != itrEnd && *itr < nMax; ++itr)
5650 93 : if (maTabs[*itr])
5651 93 : maTabs[*itr]->DeleteSelection(nDelFlag, rMark, bBroadcast);
5652 93 : }
5653 :
5654 0 : void ScDocument::DeleteSelectionTab(
5655 : SCTAB nTab, InsertDeleteFlags nDelFlag, const ScMarkData& rMark, bool bBroadcast )
5656 : {
5657 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5658 0 : maTabs[nTab]->DeleteSelection(nDelFlag, rMark, bBroadcast);
5659 : else
5660 : {
5661 : OSL_FAIL("wrong table");
5662 : }
5663 0 : }
5664 :
5665 2648192 : ScPatternAttr* ScDocument::GetDefPattern() const
5666 : {
5667 2648192 : return const_cast<ScPatternAttr*>(static_cast<const ScPatternAttr*>(&xPoolHelper->GetDocPool()->GetDefaultItem(ATTR_PATTERN)));
5668 : }
5669 :
5670 3617703 : ScDocumentPool* ScDocument::GetPool()
5671 : {
5672 3617703 : return xPoolHelper->GetDocPool();
5673 : }
5674 :
5675 82574 : ScStyleSheetPool* ScDocument::GetStyleSheetPool() const
5676 : {
5677 82574 : return xPoolHelper->GetStylePool();
5678 : }
5679 :
5680 5988 : SCSIZE ScDocument::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab,
5681 : SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, ScDirection eDir )
5682 : {
5683 5988 : PutInOrder(nStartCol, nEndCol);
5684 5988 : PutInOrder(nStartRow, nEndRow);
5685 5988 : PutInOrder(nStartTab, nEndTab);
5686 5988 : if (ValidTab(nStartTab) && nStartTab < static_cast<SCTAB>(maTabs.size()))
5687 : {
5688 5988 : if (maTabs[nStartTab])
5689 5988 : return maTabs[nStartTab]->GetEmptyLinesInBlock(nStartCol, nStartRow, nEndCol, nEndRow, eDir);
5690 : else
5691 0 : return 0;
5692 : }
5693 : else
5694 0 : return 0;
5695 : }
5696 :
5697 98 : void ScDocument::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, ScMoveDirection eDirection ) const
5698 : {
5699 98 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5700 98 : maTabs[nTab]->FindAreaPos( rCol, rRow, eDirection );
5701 98 : }
5702 :
5703 0 : void ScDocument::GetNextPos( SCCOL& rCol, SCROW& rRow, SCTAB nTab, SCsCOL nMovX, SCsROW nMovY,
5704 : bool bMarked, bool bUnprotected, const ScMarkData& rMark ) const
5705 : {
5706 : OSL_ENSURE( !nMovX || !nMovY, "GetNextPos: only X or Y" );
5707 :
5708 0 : ScMarkData aCopyMark = rMark;
5709 0 : aCopyMark.SetMarking(false);
5710 0 : aCopyMark.MarkToMulti();
5711 :
5712 0 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5713 0 : maTabs[nTab]->GetNextPos( rCol, rRow, nMovX, nMovY, bMarked, bUnprotected, aCopyMark );
5714 0 : }
5715 :
5716 : // Data operations
5717 :
5718 609 : void ScDocument::UpdStlShtPtrsFrmNms()
5719 : {
5720 609 : ScDocumentPool* pPool = xPoolHelper->GetDocPool();
5721 :
5722 609 : sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN);
5723 : ScPatternAttr* pPattern;
5724 609 : for (sal_uInt32 i=0; i<nCount; i++)
5725 : {
5726 0 : pPattern = const_cast<ScPatternAttr*>(static_cast<const ScPatternAttr*>(pPool->GetItem2(ATTR_PATTERN, i)));
5727 0 : if (pPattern)
5728 0 : pPattern->UpdateStyleSheet(this);
5729 : }
5730 609 : const_cast<ScPatternAttr&>(static_cast<const ScPatternAttr&>(pPool->GetDefaultItem(ATTR_PATTERN))).UpdateStyleSheet(this);
5731 609 : }
5732 :
5733 0 : void ScDocument::StylesToNames()
5734 : {
5735 0 : ScDocumentPool* pPool = xPoolHelper->GetDocPool();
5736 :
5737 0 : sal_uInt32 nCount = pPool->GetItemCount2(ATTR_PATTERN);
5738 : ScPatternAttr* pPattern;
5739 0 : for (sal_uInt32 i=0; i<nCount; i++)
5740 : {
5741 0 : pPattern = const_cast<ScPatternAttr*>(static_cast<const ScPatternAttr*>(pPool->GetItem2(ATTR_PATTERN, i)));
5742 0 : if (pPattern)
5743 0 : pPattern->StyleToName();
5744 : }
5745 0 : const_cast<ScPatternAttr&>(static_cast<const ScPatternAttr&>(pPool->GetDefaultItem(ATTR_PATTERN))).StyleToName();
5746 0 : }
5747 :
5748 31 : sal_uLong ScDocument::GetCellCount() const
5749 : {
5750 31 : sal_uLong nCellCount = 0L;
5751 :
5752 31 : TableContainer::const_iterator it = maTabs.begin();
5753 66 : for (; it != maTabs.end(); ++it)
5754 35 : if ( *it )
5755 35 : nCellCount += (*it)->GetCellCount();
5756 :
5757 31 : return nCellCount;
5758 : }
5759 :
5760 5 : sal_uLong ScDocument::GetFormulaGroupCount() const
5761 : {
5762 5 : sal_uLong nFormulaGroupCount = 0L;
5763 :
5764 5 : ScFormulaGroupIterator aIter( const_cast<ScDocument*>(this) );
5765 13 : for ( sc::FormulaGroupEntry* ptr = aIter.first(); ptr; ptr = aIter.next())
5766 : {
5767 8 : nFormulaGroupCount++;
5768 : }
5769 :
5770 5 : return nFormulaGroupCount;
5771 : }
5772 :
5773 0 : sal_uLong ScDocument::GetCodeCount() const
5774 : {
5775 0 : sal_uLong nCodeCount = 0;
5776 :
5777 0 : TableContainer::const_iterator it = maTabs.begin();
5778 0 : for (; it != maTabs.end(); ++it)
5779 0 : if ( *it )
5780 0 : nCodeCount += (*it)->GetCodeCount();
5781 :
5782 0 : return nCodeCount;
5783 : }
5784 :
5785 168 : void ScDocument::PageStyleModified( SCTAB nTab, const OUString& rNewName )
5786 : {
5787 168 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5788 168 : maTabs[nTab]->PageStyleModified( rNewName );
5789 168 : }
5790 :
5791 534 : void ScDocument::SetPageStyle( SCTAB nTab, const OUString& rName )
5792 : {
5793 534 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5794 534 : maTabs[nTab]->SetPageStyle( rName );
5795 534 : }
5796 :
5797 48958 : const OUString ScDocument::GetPageStyle( SCTAB nTab ) const
5798 : {
5799 48958 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5800 48958 : return maTabs[nTab]->GetPageStyle();
5801 :
5802 0 : return OUString();
5803 : }
5804 :
5805 419 : void ScDocument::SetPageSize( SCTAB nTab, const Size& rSize )
5806 : {
5807 419 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5808 419 : maTabs[nTab]->SetPageSize( rSize );
5809 419 : }
5810 :
5811 2977 : Size ScDocument::GetPageSize( SCTAB nTab ) const
5812 : {
5813 2977 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5814 2977 : return maTabs[nTab]->GetPageSize();
5815 :
5816 : OSL_FAIL("invalid tab");
5817 0 : return Size();
5818 : }
5819 :
5820 386 : void ScDocument::SetRepeatArea( SCTAB nTab, SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
5821 : {
5822 386 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5823 386 : maTabs[nTab]->SetRepeatArea( nStartCol, nEndCol, nStartRow, nEndRow );
5824 386 : }
5825 :
5826 30 : void ScDocument::InvalidatePageBreaks(SCTAB nTab)
5827 : {
5828 30 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5829 30 : maTabs[nTab]->InvalidatePageBreaks();
5830 30 : }
5831 :
5832 3187 : void ScDocument::UpdatePageBreaks( SCTAB nTab, const ScRange* pUserArea )
5833 : {
5834 3187 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5835 3187 : maTabs[nTab]->UpdatePageBreaks( pUserArea );
5836 3187 : }
5837 :
5838 0 : void ScDocument::RemoveManualBreaks( SCTAB nTab )
5839 : {
5840 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5841 0 : maTabs[nTab]->RemoveManualBreaks();
5842 0 : }
5843 :
5844 0 : bool ScDocument::HasManualBreaks( SCTAB nTab ) const
5845 : {
5846 0 : if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
5847 0 : return maTabs[nTab]->HasManualBreaks();
5848 :
5849 : OSL_FAIL("invalid tab");
5850 0 : return false;
5851 : }
5852 :
5853 0 : void ScDocument::GetDocStat( ScDocStat& rDocStat )
5854 : {
5855 0 : rDocStat.nTableCount = GetTableCount();
5856 0 : rDocStat.aDocName = aDocName;
5857 0 : rDocStat.nFormulaCount = GetFormulaGroupCount();
5858 0 : rDocStat.nCellCount = GetCellCount();
5859 0 : }
5860 :
5861 536 : bool ScDocument::HasPrintRange()
5862 : {
5863 536 : bool bResult = false;
5864 :
5865 536 : TableContainer::iterator it = maTabs.begin();
5866 1072 : for (; it != maTabs.end() && !bResult; ++it)
5867 536 : if ( *it )
5868 536 : bResult = (*it)->IsPrintEntireSheet() || ((*it)->GetPrintRangeCount() > 0);
5869 :
5870 536 : return bResult;
5871 : }
5872 :
5873 1107 : bool ScDocument::IsPrintEntireSheet( SCTAB nTab ) const
5874 : {
5875 1107 : return (ValidTab(nTab) ) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab]->IsPrintEntireSheet();
5876 : }
5877 :
5878 602 : sal_uInt16 ScDocument::GetPrintRangeCount( SCTAB nTab )
5879 : {
5880 602 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5881 602 : return maTabs[nTab]->GetPrintRangeCount();
5882 :
5883 0 : return 0;
5884 : }
5885 :
5886 407 : const ScRange* ScDocument::GetPrintRange( SCTAB nTab, sal_uInt16 nPos )
5887 : {
5888 407 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5889 407 : return maTabs[nTab]->GetPrintRange(nPos);
5890 :
5891 0 : return NULL;
5892 : }
5893 :
5894 604 : const ScRange* ScDocument::GetRepeatColRange( SCTAB nTab )
5895 : {
5896 604 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5897 604 : return maTabs[nTab]->GetRepeatColRange();
5898 :
5899 0 : return NULL;
5900 : }
5901 :
5902 610 : const ScRange* ScDocument::GetRepeatRowRange( SCTAB nTab )
5903 : {
5904 610 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5905 610 : return maTabs[nTab]->GetRepeatRowRange();
5906 :
5907 0 : return NULL;
5908 : }
5909 :
5910 60 : void ScDocument::ClearPrintRanges( SCTAB nTab )
5911 : {
5912 60 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5913 60 : maTabs[nTab]->ClearPrintRanges();
5914 60 : }
5915 :
5916 8 : void ScDocument::AddPrintRange( SCTAB nTab, const ScRange& rNew )
5917 : {
5918 8 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5919 8 : maTabs[nTab]->AddPrintRange( rNew );
5920 8 : }
5921 :
5922 11 : void ScDocument::SetPrintEntireSheet( SCTAB nTab )
5923 : {
5924 11 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5925 11 : maTabs[nTab]->SetPrintEntireSheet();
5926 11 : }
5927 :
5928 1 : void ScDocument::SetRepeatColRange( SCTAB nTab, const ScRange* pNew )
5929 : {
5930 1 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5931 1 : maTabs[nTab]->SetRepeatColRange( pNew );
5932 1 : }
5933 :
5934 5 : void ScDocument::SetRepeatRowRange( SCTAB nTab, const ScRange* pNew )
5935 : {
5936 5 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5937 5 : maTabs[nTab]->SetRepeatRowRange( pNew );
5938 5 : }
5939 :
5940 140 : ScPrintRangeSaver* ScDocument::CreatePrintRangeSaver() const
5941 : {
5942 140 : SCTAB nCount = static_cast<SCTAB>(maTabs.size());
5943 140 : ScPrintRangeSaver* pNew = new ScPrintRangeSaver( nCount );
5944 346 : for (SCTAB i=0; i<nCount; i++)
5945 206 : if (maTabs[i])
5946 206 : maTabs[i]->FillPrintSaver( pNew->GetTabData(i) );
5947 140 : return pNew;
5948 : }
5949 :
5950 2 : void ScDocument::RestorePrintRanges( const ScPrintRangeSaver& rSaver )
5951 : {
5952 2 : SCTAB nCount = rSaver.GetTabCount();
5953 6 : for (SCTAB i=0; i<nCount && i < static_cast<SCTAB>(maTabs.size()); i++)
5954 4 : if (maTabs[i])
5955 4 : maTabs[i]->RestorePrintRanges( rSaver.GetTabData(i) );
5956 2 : }
5957 :
5958 2 : bool ScDocument::NeedPageResetAfterTab( SCTAB nTab ) const
5959 : {
5960 : // The page number count restarts at a sheet, if another template is set at
5961 : // the preseding one (oly compare names) and if a pagenumber is specified (not 0)
5962 :
5963 2 : if ( nTab + 1 < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] && maTabs[nTab+1] )
5964 : {
5965 2 : OUString aNew = maTabs[nTab+1]->GetPageStyle();
5966 2 : if ( aNew != maTabs[nTab]->GetPageStyle() )
5967 : {
5968 0 : SfxStyleSheetBase* pStyle = xPoolHelper->GetStylePool()->Find( aNew, SFX_STYLE_FAMILY_PAGE );
5969 0 : if ( pStyle )
5970 : {
5971 0 : const SfxItemSet& rSet = pStyle->GetItemSet();
5972 0 : sal_uInt16 nFirst = static_cast<const SfxUInt16Item&>(rSet.Get(ATTR_PAGE_FIRSTPAGENO)).GetValue();
5973 0 : if ( nFirst != 0 )
5974 0 : return true; // Specify page number in new template
5975 : }
5976 2 : }
5977 : }
5978 :
5979 2 : return false; // otherwise not
5980 : }
5981 :
5982 49630 : SfxUndoManager* ScDocument::GetUndoManager()
5983 : {
5984 49630 : if (!mpUndoManager)
5985 : {
5986 : // to support enhanced text edit for draw objects, use an SdrUndoManager
5987 648 : mpUndoManager = new SdrUndoManager;
5988 : }
5989 :
5990 49630 : return mpUndoManager;
5991 : }
5992 :
5993 65 : ScRowBreakIterator* ScDocument::GetRowBreakIterator(SCTAB nTab) const
5994 : {
5995 65 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
5996 65 : return new ScRowBreakIterator(maTabs[nTab]->maRowPageBreaks);
5997 0 : return NULL;
5998 : }
5999 :
6000 766 : void ScDocument::AddSubTotalCell(ScFormulaCell* pCell)
6001 : {
6002 766 : maSubTotalCells.insert(pCell);
6003 766 : }
6004 :
6005 10243 : void ScDocument::RemoveSubTotalCell(ScFormulaCell* pCell)
6006 : {
6007 10243 : maSubTotalCells.erase(pCell);
6008 10243 : }
6009 :
6010 : namespace {
6011 :
6012 0 : bool lcl_hasDirtyRange(ScFormulaCell* pCell, const ScRange& rDirtyRange)
6013 : {
6014 0 : ScDetectiveRefIter aRefIter(pCell);
6015 0 : ScRange aRange;
6016 0 : while (aRefIter.GetNextRef(aRange))
6017 : {
6018 0 : if (aRange.Intersects(rDirtyRange))
6019 0 : return true;
6020 : }
6021 0 : return false;
6022 : }
6023 :
6024 : }
6025 :
6026 14 : void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange)
6027 : {
6028 : // to update the list by skipping cells that no longer contain subtotal function.
6029 14 : set<ScFormulaCell*> aNewSet;
6030 :
6031 14 : bool bOldRecalc = GetAutoCalc();
6032 14 : SetAutoCalc(false);
6033 14 : set<ScFormulaCell*>::iterator itr = maSubTotalCells.begin(), itrEnd = maSubTotalCells.end();
6034 14 : for (; itr != itrEnd; ++itr)
6035 : {
6036 0 : ScFormulaCell* pCell = *itr;
6037 0 : if (pCell->IsSubTotal())
6038 : {
6039 0 : aNewSet.insert(pCell);
6040 0 : if (lcl_hasDirtyRange(pCell, rDirtyRange))
6041 0 : pCell->SetDirty();
6042 : }
6043 : }
6044 :
6045 14 : SetAutoCalc(bOldRecalc);
6046 14 : maSubTotalCells.swap(aNewSet); // update the list.
6047 14 : }
6048 :
6049 1 : sal_uInt16 ScDocument::GetTextWidth( const ScAddress& rPos ) const
6050 : {
6051 1 : SCTAB nTab = rPos.Tab();
6052 1 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
6053 1 : return maTabs[nTab]->GetTextWidth(rPos.Col(), rPos.Row());
6054 :
6055 0 : return 0;
6056 : }
6057 :
6058 31225 : SvtScriptType ScDocument::GetScriptType( const ScAddress& rPos ) const
6059 : {
6060 31225 : SCTAB nTab = rPos.Tab();
6061 31225 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
6062 31225 : return maTabs[nTab]->GetScriptType(rPos.Col(), rPos.Row());
6063 :
6064 0 : return SvtScriptType::NONE;
6065 : }
6066 :
6067 3499 : void ScDocument::SetScriptType( const ScAddress& rPos, SvtScriptType nType )
6068 : {
6069 3499 : SCTAB nTab = rPos.Tab();
6070 3499 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab])
6071 3499 : maTabs[nTab]->SetScriptType(rPos.Col(), rPos.Row(), nType);
6072 3499 : }
6073 :
6074 21574 : void ScDocument::EnableUndo( bool bVal )
6075 : {
6076 : // The undo manager increases lock count every time undo is disabled.
6077 : // Because of this, we shouldn't disable undo unless it's currently
6078 : // enabled, or else re-enabling it may not actually re-enable undo unless
6079 : // the lock count becomes zero.
6080 :
6081 21574 : if (bVal != GetUndoManager()->IsUndoEnabled())
6082 : {
6083 16284 : GetUndoManager()->EnableUndo(bVal);
6084 16284 : if( pDrawLayer ) pDrawLayer->EnableUndo(bVal);
6085 : }
6086 :
6087 21574 : mbUndoEnabled = bVal;
6088 21574 : }
6089 :
6090 246 : void ScDocument::EnableUserInteraction( bool bVal )
6091 : {
6092 246 : mbUserInteractionEnabled = bVal;
6093 246 : }
6094 :
6095 278 : bool ScDocument::IsInVBAMode() const
6096 : {
6097 278 : if (!pShell)
6098 1 : return false;
6099 :
6100 : try
6101 : {
6102 : uno::Reference<script::vba::XVBACompatibility> xVBA(
6103 277 : pShell->GetBasicContainer(), uno::UNO_QUERY);
6104 :
6105 277 : return xVBA.is() && xVBA->getVBACompatibilityMode();
6106 : }
6107 0 : catch (const lang::NotInitializedException&) {}
6108 :
6109 0 : return false;
6110 : }
6111 :
6112 1002 : ScPostIt* ScDocument::GetNote(const ScAddress& rPos)
6113 : {
6114 1002 : return GetNote(rPos.Col(), rPos.Row(), rPos.Tab());
6115 : }
6116 :
6117 207031 : ScPostIt* ScDocument::GetNote(SCCOL nCol, SCROW nRow, SCTAB nTab)
6118 : {
6119 207031 : if (ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()))
6120 207031 : return maTabs[nTab]->aCol[nCol].GetCellNote(nRow);
6121 : else
6122 0 : return NULL;
6123 :
6124 : }
6125 :
6126 72 : void ScDocument::SetNote(const ScAddress& rPos, ScPostIt* pNote)
6127 : {
6128 72 : return SetNote(rPos.Col(), rPos.Row(), rPos.Tab(), pNote);
6129 : }
6130 :
6131 72 : void ScDocument::SetNote(SCCOL nCol, SCROW nRow, SCTAB nTab, ScPostIt* pNote)
6132 : {
6133 72 : return maTabs[nTab]->aCol[nCol].SetCellNote(nRow, pNote);
6134 : }
6135 :
6136 122 : bool ScDocument::HasNote(const ScAddress& rPos) const
6137 : {
6138 122 : return HasNote(rPos.Col(), rPos.Row(), rPos.Tab());
6139 : }
6140 :
6141 131 : bool ScDocument::HasNote(SCCOL nCol, SCROW nRow, SCTAB nTab) const
6142 : {
6143 131 : if (!ValidColRow(nCol, nRow))
6144 0 : return false;
6145 :
6146 131 : const ScTable* pTab = FetchTable(nTab);
6147 131 : if (!pTab)
6148 0 : return false;
6149 :
6150 131 : const ScPostIt* pNote = pTab->aCol[nCol].GetCellNote(nRow);
6151 131 : return pNote != NULL;
6152 : }
6153 :
6154 20480003 : bool ScDocument::HasColNotes(SCCOL nCol, SCTAB nTab) const
6155 : {
6156 20480003 : if (!ValidCol(nCol))
6157 0 : return false;
6158 :
6159 20480003 : const ScTable* pTab = FetchTable(nTab);
6160 20480003 : if (!pTab)
6161 20477952 : return false;
6162 :
6163 2051 : return pTab->aCol[nCol].HasCellNotes();
6164 : }
6165 :
6166 20000 : bool ScDocument::HasTabNotes(SCTAB nTab) const
6167 : {
6168 20000 : bool hasNotes = false;
6169 20500000 : for (SCCOL nCol=0; nCol<MAXCOLCOUNT && !hasNotes; ++nCol)
6170 20480000 : hasNotes = HasColNotes(nCol, nTab);
6171 :
6172 20000 : return hasNotes;
6173 : }
6174 :
6175 1 : bool ScDocument::HasNotes() const
6176 : {
6177 10001 : for (SCTAB i = 0; i <= MAXTAB; ++i)
6178 : {
6179 10000 : if (HasTabNotes(i))
6180 0 : return true;
6181 : }
6182 1 : return false;
6183 : }
6184 :
6185 21 : ScPostIt* ScDocument::ReleaseNote(const ScAddress& rPos)
6186 : {
6187 21 : ScTable* pTab = FetchTable(rPos.Tab());
6188 21 : if (!pTab)
6189 0 : return NULL;
6190 :
6191 21 : return pTab->ReleaseNote(rPos.Col(), rPos.Row());
6192 : }
6193 :
6194 28 : ScPostIt* ScDocument::GetOrCreateNote(const ScAddress& rPos)
6195 : {
6196 28 : if (HasNote(rPos))
6197 0 : return GetNote(rPos);
6198 : else
6199 28 : return CreateNote(rPos);
6200 : }
6201 28 : ScPostIt* ScDocument::CreateNote(const ScAddress& rPos)
6202 : {
6203 28 : ScPostIt* pPostIt = new ScPostIt(*this, rPos, false);
6204 28 : SetNote(rPos, pPostIt);
6205 28 : return pPostIt;
6206 : }
6207 :
6208 1056 : size_t ScDocument::GetNoteCount( SCTAB nTab, SCCOL nCol ) const
6209 : {
6210 1056 : const ScTable* pTab = FetchTable(nTab);
6211 1056 : if (!pTab)
6212 0 : return 0;
6213 :
6214 1056 : return pTab->GetNoteCount(nCol);
6215 : }
6216 :
6217 30 : void ScDocument::CreateAllNoteCaptions()
6218 : {
6219 30 : TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end();
6220 64 : for (; it != itEnd; ++it)
6221 : {
6222 34 : ScTable* p = *it;
6223 34 : if (p)
6224 34 : p->CreateAllNoteCaptions();
6225 : }
6226 30 : }
6227 :
6228 8 : void ScDocument::ForgetNoteCaptions( const ScRangeList& rRanges )
6229 : {
6230 16 : for (size_t i = 0, n = rRanges.size(); i < n; ++i)
6231 : {
6232 8 : const ScRange* p = rRanges[i];
6233 8 : const ScAddress& s = p->aStart;
6234 8 : const ScAddress& e = p->aEnd;
6235 16 : for (SCTAB nTab = s.Tab(); nTab <= e.Tab(); ++nTab)
6236 : {
6237 8 : ScTable* pTab = FetchTable(nTab);
6238 8 : if (!pTab)
6239 0 : continue;
6240 :
6241 8 : pTab->ForgetNoteCaptions(s.Col(), s.Row(), e.Col(), e.Row());
6242 : }
6243 : }
6244 8 : }
6245 :
6246 0 : ScAddress ScDocument::GetNotePosition( size_t nIndex ) const
6247 : {
6248 0 : for (size_t nTab = 0; nTab < maTabs.size(); ++nTab)
6249 : {
6250 0 : for (SCCOL nCol=0; nCol<MAXCOLCOUNT; nCol++)
6251 : {
6252 0 : size_t nColNoteCount = GetNoteCount(nTab, nCol);
6253 0 : if (!nColNoteCount)
6254 0 : continue;
6255 :
6256 0 : if (nIndex >= nColNoteCount)
6257 : {
6258 0 : nIndex -= nColNoteCount;
6259 0 : continue;
6260 : }
6261 :
6262 0 : SCROW nRow = GetNotePosition(nTab, nCol, nIndex);
6263 0 : if (nRow >= 0)
6264 0 : return ScAddress(nCol, nRow, nTab);
6265 :
6266 : OSL_FAIL("note not found");
6267 0 : return ScAddress(ScAddress::INITIALIZE_INVALID);
6268 : }
6269 : }
6270 :
6271 : OSL_FAIL("note not found");
6272 0 : return ScAddress(ScAddress::INITIALIZE_INVALID);
6273 : }
6274 :
6275 7 : ScAddress ScDocument::GetNotePosition( size_t nIndex, SCTAB nTab ) const
6276 : {
6277 1057 : for (SCCOL nCol=0; nCol<MAXCOLCOUNT; nCol++)
6278 : {
6279 1056 : size_t nColNoteCount = GetNoteCount(nTab, nCol);
6280 1056 : if (!nColNoteCount)
6281 1039 : continue;
6282 :
6283 17 : if (nIndex >= nColNoteCount)
6284 : {
6285 11 : nIndex -= nColNoteCount;
6286 11 : continue;
6287 : }
6288 :
6289 6 : SCROW nRow = GetNotePosition(nTab, nCol, nIndex);
6290 6 : if (nRow >= 0)
6291 6 : return ScAddress(nCol, nRow, nTab);
6292 :
6293 : OSL_FAIL("note not found");
6294 0 : return ScAddress(ScAddress::INITIALIZE_INVALID);
6295 : }
6296 :
6297 : OSL_FAIL("note not found");
6298 1 : return ScAddress(ScAddress::INITIALIZE_INVALID);
6299 : }
6300 :
6301 6 : SCROW ScDocument::GetNotePosition( SCTAB nTab, SCCOL nCol, size_t nIndex ) const
6302 : {
6303 6 : const ScTable* pTab = FetchTable(nTab);
6304 6 : if (!pTab)
6305 0 : return -1;
6306 :
6307 6 : return pTab->GetNotePosition(nCol, nIndex);
6308 : }
6309 :
6310 129 : void ScDocument::GetAllNoteEntries( std::vector<sc::NoteEntry>& rNotes ) const
6311 : {
6312 424 : for (size_t nTab = 0; nTab < maTabs.size(); ++nTab)
6313 : {
6314 295 : const ScTable* pTab = maTabs[nTab];
6315 295 : if (!pTab)
6316 0 : continue;
6317 :
6318 295 : pTab->GetAllNoteEntries(rNotes);
6319 : }
6320 129 : }
6321 :
6322 12 : void ScDocument::GetNotesInRange( const ScRangeList& rRange, std::vector<sc::NoteEntry>& rNotes ) const
6323 : {
6324 24 : for( size_t i = 0; i < rRange.size(); ++i)
6325 : {
6326 12 : const ScRange* pRange = rRange[i];
6327 24 : for( SCTAB nTab = pRange->aStart.Tab(); nTab <= pRange->aEnd.Tab(); ++nTab )
6328 : {
6329 12 : maTabs[nTab]->GetNotesInRange( *pRange, rNotes );
6330 : }
6331 : }
6332 12 : }
6333 :
6334 0 : bool ScDocument::ContainsNotesInRange( const ScRangeList& rRange ) const
6335 : {
6336 0 : for( size_t i = 0; i < rRange.size(); ++i)
6337 : {
6338 0 : const ScRange* pRange = rRange[i];
6339 0 : for( SCTAB nTab = pRange->aStart.Tab(); nTab < pRange->aEnd.Tab(); ++nTab )
6340 : {
6341 0 : bool bContainsNote = maTabs[nTab]->ContainsNotesInRange( *pRange );
6342 0 : if(bContainsNote)
6343 0 : return true;
6344 : }
6345 : }
6346 :
6347 0 : return false;
6348 : }
6349 :
6350 290 : void ScDocument::SetAutoNameCache( ScAutoNameCache* pCache )
6351 : {
6352 290 : delete pAutoNameCache;
6353 290 : pAutoNameCache = pCache;
6354 446 : }
6355 :
6356 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|