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