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