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