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