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