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