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