xref: /AOO41X/main/sc/source/core/data/table1.cxx (revision 557cb41289f925cf858b5e9eb122ac9e2590bc06)
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 #include "scitems.hxx"
30 #include <svx/algitem.hxx>
31 #include <unotools/textsearch.hxx>
32 #include <sfx2/objsh.hxx>
33 
34 #include "attrib.hxx"
35 #include "patattr.hxx"
36 #include "cell.hxx"
37 #include "table.hxx"
38 #include "document.hxx"
39 #include "drwlayer.hxx"
40 #include "olinetab.hxx"
41 #include "stlsheet.hxx"
42 #include "global.hxx"
43 #include "globstr.hrc"
44 #include "refupdat.hxx"
45 #include "markdata.hxx"
46 #include "progress.hxx"
47 #include "hints.hxx"        // fuer Paint-Broadcast
48 #include "prnsave.hxx"
49 #include "tabprotection.hxx"
50 #include "sheetevents.hxx"
51 #include "segmenttree.hxx"
52 
53 // -----------------------------------------------------------------------
54 
ScTable(ScDocument * pDoc,SCTAB nNewTab,const String & rNewName,sal_Bool bColInfo,sal_Bool bRowInfo)55 ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName,
56                     sal_Bool bColInfo, sal_Bool bRowInfo ) :
57     aName( rNewName ),
58     aCodeName( rNewName ),
59     bScenario( sal_False ),
60     bLayoutRTL( sal_False ),
61     bLoadingRTL( sal_False ),
62     nLinkMode( 0 ),
63     aPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD) ),
64     bPageSizeValid( sal_False ),
65     nRepeatStartX( SCCOL_REPEAT_NONE ),
66     nRepeatStartY( SCROW_REPEAT_NONE ),
67     pTabProtection( NULL ),
68     pColWidth( NULL ),
69     mpRowHeights( static_cast<ScFlatUInt16RowSegments*>(NULL) ),
70     pColFlags( NULL ),
71     pRowFlags( NULL ),
72     mpHiddenCols(new ScFlatBoolColSegments),
73     mpHiddenRows(new ScFlatBoolRowSegments),
74     mpFilteredCols(new ScFlatBoolColSegments),
75     mpFilteredRows(new ScFlatBoolRowSegments),
76     pOutlineTable( NULL ),
77     pSheetEvents( NULL ),
78     bTableAreaValid( sal_False ),
79     bVisible( sal_True ),
80     bStreamValid( sal_False ),
81     bPendingRowHeights( sal_False ),
82     bCalcNotification( sal_False ),
83     nTab( nNewTab ),
84     nRecalcLvl( 0 ),
85     pDocument( pDoc ),
86     pSearchParam( NULL ),
87     pSearchText ( NULL ),
88     pSortCollator( NULL ),
89     bPrintEntireSheet( sal_False ),
90     pRepeatColRange( NULL ),
91     pRepeatRowRange( NULL ),
92     nLockCount( 0 ),
93     pScenarioRanges( NULL ),
94     aScenarioColor( COL_LIGHTGRAY ),
95     aTabBgColor( COL_AUTO ),
96     nScenarioFlags( 0 ),
97     bActiveScenario( sal_False ),
98     mbPageBreaksValid(false)
99 {
100 
101     if (bColInfo)
102     {
103         pColWidth  = new sal_uInt16[ MAXCOL+1 ];
104         pColFlags  = new sal_uInt8[ MAXCOL+1 ];
105 
106         for (SCCOL i=0; i<=MAXCOL; i++)
107         {
108             pColWidth[i] = STD_COL_WIDTH;
109             pColFlags[i] = 0;
110         }
111     }
112 
113     if (bRowInfo)
114     {
115         mpRowHeights.reset(new ScFlatUInt16RowSegments(ScGlobal::nStdRowHeight));
116         pRowFlags  = new ScBitMaskCompressedArray< SCROW, sal_uInt8>( MAXROW, 0);
117     }
118 
119     if ( pDocument->IsDocVisible() )
120     {
121         //  when a sheet is added to a visible document,
122         //  initialize its RTL flag from the system locale
123         bLayoutRTL = ScGlobal::IsSystemRTL();
124     }
125 
126     ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
127     if (pDrawLayer)
128     {
129         if ( pDrawLayer->ScAddPage( nTab ) )    // sal_False (not inserted) during Undo
130         {
131             pDrawLayer->ScRenamePage( nTab, aName );
132             sal_uLong nx = (sal_uLong) ((double) (MAXCOL+1) * STD_COL_WIDTH           * HMM_PER_TWIPS );
133             sal_uLong ny = (sal_uLong) ((double) (MAXROW+1) * ScGlobal::nStdRowHeight * HMM_PER_TWIPS );
134             pDrawLayer->SetPageSize( static_cast<sal_uInt16>(nTab), Size( nx, ny ), false );
135         }
136     }
137 
138     for (SCCOL k=0; k<=MAXCOL; k++)
139         aCol[k].Init( k, nTab, pDocument );
140 }
141 
~ScTable()142 ScTable::~ScTable()
143 {
144     if (!pDocument->IsInDtorClear())
145     {
146         //  nicht im dtor die Pages in der falschen Reihenfolge loeschen
147         //  (nTab stimmt dann als Page-Number nicht!)
148         //  In ScDocument::Clear wird hinterher per Clear am Draw Layer alles geloescht.
149 
150         ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
151         if (pDrawLayer)
152             pDrawLayer->ScRemovePage( nTab );
153     }
154 
155     delete[] pColWidth;
156     delete[] pColFlags;
157     delete pRowFlags;
158     delete pSheetEvents;
159     delete pOutlineTable;
160     delete pSearchParam;
161     delete pSearchText;
162     delete pRepeatColRange;
163     delete pRepeatRowRange;
164     delete pScenarioRanges;
165     DestroySortCollator();
166 }
167 
GetName(String & rName) const168 void ScTable::GetName( String& rName ) const
169 {
170     rName = aName;
171 }
172 
SetName(const String & rNewName)173 void ScTable::SetName( const String& rNewName )
174 {
175     aName = rNewName;
176     aUpperName.Erase();         // invalidated if the name is changed
177 
178     // SetStreamValid is handled in ScDocument::RenameTab
179 }
180 
GetUpperName() const181 const String& ScTable::GetUpperName() const
182 {
183     if ( !aUpperName.Len() && aName.Len() )
184         aUpperName = ScGlobal::pCharClass->upper( aName );
185     return aUpperName;
186 }
187 
SetVisible(sal_Bool bVis)188 void ScTable::SetVisible( sal_Bool bVis )
189 {
190     if (bVisible != bVis && IsStreamValid())
191         SetStreamValid(sal_False);
192 
193     bVisible = bVis;
194 }
195 
SetStreamValid(sal_Bool bSet,sal_Bool bIgnoreLock)196 void ScTable::SetStreamValid( sal_Bool bSet, sal_Bool bIgnoreLock )
197 {
198     if ( bIgnoreLock || !pDocument->IsStreamValidLocked() )
199         bStreamValid = bSet;
200 }
201 
SetPendingRowHeights(sal_Bool bSet)202 void ScTable::SetPendingRowHeights( sal_Bool bSet )
203 {
204     bPendingRowHeights = bSet;
205 }
206 
SetLayoutRTL(sal_Bool bSet)207 void ScTable::SetLayoutRTL( sal_Bool bSet )
208 {
209     bLayoutRTL = bSet;
210 }
211 
SetLoadingRTL(sal_Bool bSet)212 void ScTable::SetLoadingRTL( sal_Bool bSet )
213 {
214     bLoadingRTL = bSet;
215 }
216 
GetTabBgColor() const217 const Color& ScTable::GetTabBgColor() const
218 {
219     return aTabBgColor;
220 }
221 
SetTabBgColor(const Color & rColor)222 void ScTable::SetTabBgColor(const Color& rColor)
223 {
224     if (aTabBgColor != rColor)
225     {
226         // The tab color has changed.  Set this table 'modified'.
227         aTabBgColor = rColor;
228         if (IsStreamValid())
229             SetStreamValid(false);
230     }
231 }
232 
SetScenario(sal_Bool bFlag)233 void ScTable::SetScenario( sal_Bool bFlag )
234 {
235     bScenario = bFlag;
236 }
237 
SetLink(sal_uInt8 nMode,const String & rDoc,const String & rFlt,const String & rOpt,const String & rTab,sal_uLong nRefreshDelay)238 void ScTable::SetLink( sal_uInt8 nMode,
239                         const String& rDoc, const String& rFlt, const String& rOpt,
240                         const String& rTab, sal_uLong nRefreshDelay )
241 {
242     nLinkMode = nMode;
243     aLinkDoc = rDoc;        // Datei
244     aLinkFlt = rFlt;        // Filter
245     aLinkOpt = rOpt;        // Filter-Optionen
246     aLinkTab = rTab;        // Tabellenname in Quelldatei
247     nLinkRefreshDelay = nRefreshDelay;  // refresh delay in seconds, 0==off
248 
249     if (IsStreamValid())
250         SetStreamValid(sal_False);
251 }
252 
GetOptimalColWidth(SCCOL nCol,OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,sal_Bool bFormula,const ScMarkData * pMarkData,sal_Bool bSimpleTextImport)253 sal_uInt16 ScTable::GetOptimalColWidth( SCCOL nCol, OutputDevice* pDev,
254                                     double nPPTX, double nPPTY,
255                                     const Fraction& rZoomX, const Fraction& rZoomY,
256                                     sal_Bool bFormula, const ScMarkData* pMarkData,
257                                     sal_Bool bSimpleTextImport )
258 {
259     return aCol[nCol].GetOptimalColWidth( pDev, nPPTX, nPPTY, rZoomX, rZoomY,
260         bFormula, STD_COL_WIDTH - STD_EXTRA_WIDTH, pMarkData, bSimpleTextImport );
261 }
262 
GetNeededSize(SCCOL nCol,SCROW nRow,OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,sal_Bool bWidth,sal_Bool bTotalSize)263 long ScTable::GetNeededSize( SCCOL nCol, SCROW nRow,
264                                 OutputDevice* pDev,
265                                 double nPPTX, double nPPTY,
266                                 const Fraction& rZoomX, const Fraction& rZoomY,
267                                 sal_Bool bWidth, sal_Bool bTotalSize )
268 {
269     ScNeededSizeOptions aOptions;
270     aOptions.bSkipMerged = sal_False;       // zusammengefasste mitzaehlen
271     aOptions.bTotalSize  = bTotalSize;
272 
273     return aCol[nCol].GetNeededSize
274         ( nRow, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bWidth, aOptions );
275 }
276 
SetOptimalHeight(SCROW nStartRow,SCROW nEndRow,sal_uInt16 nExtra,OutputDevice * pDev,double nPPTX,double nPPTY,const Fraction & rZoomX,const Fraction & rZoomY,sal_Bool bForce,ScProgress * pOuterProgress,sal_uLong nProgressStart)277 sal_Bool ScTable::SetOptimalHeight( SCROW nStartRow, SCROW nEndRow, sal_uInt16 nExtra,
278                                 OutputDevice* pDev,
279                                 double nPPTX, double nPPTY,
280                                 const Fraction& rZoomX, const Fraction& rZoomY,
281                                 sal_Bool bForce, ScProgress* pOuterProgress, sal_uLong nProgressStart )
282 {
283     DBG_ASSERT( nExtra==0 || bForce, "autom. OptimalHeight mit Extra" );
284 
285     if ( !pDocument->IsAdjustHeightEnabled() )
286     {
287         return sal_False;
288     }
289 
290     sal_Bool    bChanged = sal_False;
291     SCSIZE  nCount = static_cast<SCSIZE>(nEndRow-nStartRow+1);
292 
293     ScProgress* pProgress = NULL;
294     if ( pOuterProgress )
295         pProgress = pOuterProgress;
296     else if ( nCount > 1 )
297         pProgress = new ScProgress( pDocument->GetDocumentShell(),
298                             ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), GetWeightedCount() );
299 
300     sal_uInt16* pHeight = new sal_uInt16[nCount];                   // Twips !
301     memset( pHeight, 0, sizeof(sal_uInt16) * nCount );
302 
303     //  zuerst einmal ueber den ganzen Bereich
304     //  (mit der letzten Spalte in der Hoffnung, dass die am ehesten noch auf
305     //   Standard formatiert ist)
306 
307     aCol[MAXCOL].GetOptimalHeight(
308             nStartRow, nEndRow, pHeight, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bForce, 0, 0 );
309 
310     //  daraus Standardhoehe suchen, die im unteren Bereich gilt
311 
312     sal_uInt16 nMinHeight = pHeight[nCount-1];
313     SCSIZE nPos = nCount-1;
314     while ( nPos && pHeight[nPos-1] >= nMinHeight )
315         --nPos;
316     SCROW nMinStart = nStartRow + nPos;
317 
318     sal_uLong nWeightedCount = 0;
319     for (SCCOL nCol=0; nCol<MAXCOL; nCol++)     // MAXCOL schon oben
320     {
321         aCol[nCol].GetOptimalHeight(
322             nStartRow, nEndRow, pHeight, pDev, nPPTX, nPPTY, rZoomX, rZoomY, bForce,
323             nMinHeight, nMinStart );
324 
325         if (pProgress)
326         {
327             sal_uLong nWeight = aCol[nCol].GetWeightedCount();
328             if (nWeight)        // nochmal denselben Status muss auch nicht sein
329             {
330                 nWeightedCount += nWeight;
331                 pProgress->SetState( nWeightedCount + nProgressStart );
332             }
333         }
334     }
335 
336     IncRecalcLevel();       // #i116460# avoid problems with Excel files
337 
338     SCROW nRngStart = 0;
339     SCROW nRngEnd = 0;
340     sal_uInt16 nLast = 0;
341     for (SCSIZE i=0; i<nCount; i++)
342     {
343         size_t nIndex;
344         SCROW nRegionEndRow;
345         sal_uInt8 nRowFlag = pRowFlags->GetValue( nStartRow+i, nIndex, nRegionEndRow );
346         if ( nRegionEndRow > nEndRow )
347             nRegionEndRow = nEndRow;
348         SCSIZE nMoreRows = nRegionEndRow - ( nStartRow+i );     // additional equal rows after first
349 
350         bool bAutoSize = ((nRowFlag & CR_MANUALSIZE) == 0);
351         if ( bAutoSize || bForce )
352         {
353             if (nExtra)
354             {
355                 if (bAutoSize)
356                     pRowFlags->SetValue( nStartRow+i, nRegionEndRow, nRowFlag | CR_MANUALSIZE);
357             }
358             else if (!bAutoSize)
359                 pRowFlags->SetValue( nStartRow+i, nRegionEndRow, nRowFlag & ~CR_MANUALSIZE);
360 
361             for (SCSIZE nInner = i; nInner <= i + nMoreRows; ++nInner)
362             {
363                 if (nLast)
364                 {
365                     if (pHeight[nInner]+nExtra == nLast)
366                         nRngEnd = nStartRow+nInner;
367                     else
368                     {
369                         bChanged |= SetRowHeightRange( nRngStart, nRngEnd, nLast, nPPTX, nPPTY );
370                         nLast = 0;
371                     }
372                 }
373                 if (!nLast)
374                 {
375                     nLast = pHeight[nInner]+nExtra;
376                     nRngStart = nStartRow+nInner;
377                     nRngEnd = nStartRow+nInner;
378                 }
379             }
380         }
381         else
382         {
383             if (nLast)
384                 bChanged |= SetRowHeightRange( nRngStart, nRngEnd, nLast, nPPTX, nPPTY );
385             nLast = 0;
386         }
387         i += nMoreRows;     // already handled - skip
388     }
389     if (nLast)
390         bChanged |= SetRowHeightRange( nRngStart, nRngEnd, nLast, nPPTX, nPPTY );
391 
392     DecRecalcLevel();       // #i116460# avoid problems with Excel files
393 
394     delete[] pHeight;
395     if ( pProgress != pOuterProgress )
396         delete pProgress;
397 
398     return bChanged;
399 }
400 
GetCellArea(SCCOL & rEndCol,SCROW & rEndRow) const401 sal_Bool ScTable::GetCellArea( SCCOL& rEndCol, SCROW& rEndRow ) const
402 {
403     sal_Bool bFound = sal_False;
404     SCCOL nMaxX = 0;
405     SCROW nMaxY = 0;
406     for (SCCOL i=0; i<=MAXCOL; i++)
407         if (!aCol[i].IsEmptyVisData(sal_True))      // sal_True = Notizen zaehlen auch
408         {
409             bFound = sal_True;
410             nMaxX = i;
411             SCROW nColY = aCol[i].GetLastVisDataPos(sal_True);
412             if (nColY > nMaxY)
413                 nMaxY = nColY;
414         }
415 
416     rEndCol = nMaxX;
417     rEndRow = nMaxY;
418     return bFound;
419 }
420 
GetTableArea(SCCOL & rEndCol,SCROW & rEndRow) const421 sal_Bool ScTable::GetTableArea( SCCOL& rEndCol, SCROW& rEndRow ) const
422 {
423     sal_Bool bRet = sal_True;               //! merken?
424     if (!bTableAreaValid)
425     {
426         bRet = GetPrintArea( ((ScTable*)this)->nTableAreaX,
427                                 ((ScTable*)this)->nTableAreaY, sal_True );
428         ((ScTable*)this)->bTableAreaValid = sal_True;
429     }
430     rEndCol = nTableAreaX;
431     rEndRow = nTableAreaY;
432     return bRet;
433 }
434 
GetLastAttrCell(SCCOL & rEndCol,SCROW & rEndRow) const435 void ScTable::GetLastAttrCell( SCCOL& rEndCol, SCROW& rEndRow ) const
436 {
437     SCCOL nMaxX = 0;
438     SCROW nMaxY = 0;
439     SCCOL i;
440     for ( i = 0; i <= MAXCOL; i++ )
441     {
442         SCROW nLastRow;
443         aCol[i].GetLastAttr( nLastRow );
444         if ( nLastRow > nMaxY && nLastRow > 0 && nLastRow <= MAXROW )
445         {
446             nMaxY = nLastRow;
447             nMaxX = i;
448         }
449     }
450     rEndCol = nMaxX;
451     rEndRow = nMaxY;
452 }
453 /*      vorher:
454 
455     sal_Bool bFound = sal_False;
456     SCCOL nMaxX = 0;
457     SCROW nMaxY = 0;
458     for (SCCOL i=0; i<=MAXCOL; i++)
459         if (!aCol[i].IsEmpty())
460         {
461             bFound = sal_True;
462             nMaxX = i;
463             SCCOL nColY = aCol[i].GetLastEntryPos();
464             if (nColY > nMaxY)
465                 nMaxY = nColY;
466         }
467 
468     rEndCol = nMaxX;
469     rEndRow = nMaxY;
470     return bFound;
471 */
472 
473 const SCCOL SC_COLUMNS_STOP = 30;
474 
GetPrintArea(SCCOL & rEndCol,SCROW & rEndRow,sal_Bool bNotes) const475 sal_Bool ScTable::GetPrintArea( SCCOL& rEndCol, SCROW& rEndRow, sal_Bool bNotes ) const
476 {
477     sal_Bool bFound = sal_False;
478     SCCOL nMaxX = 0;
479     SCROW nMaxY = 0;
480     SCCOL i;
481 
482     for (i=0; i<=MAXCOL; i++)               // Daten testen
483         if (!aCol[i].IsEmptyVisData(bNotes))
484         {
485             bFound = sal_True;
486             if (i>nMaxX)
487                 nMaxX = i;
488             SCROW nColY = aCol[i].GetLastVisDataPos(bNotes);
489             if (nColY > nMaxY)
490                 nMaxY = nColY;
491         }
492 
493     SCCOL nMaxDataX = nMaxX;
494 
495     for (i=0; i<=MAXCOL; i++)               // Attribute testen
496     {
497         SCROW nLastRow;
498         if (aCol[i].GetLastVisibleAttr( nLastRow ))
499         {
500             bFound = sal_True;
501             nMaxX = i;
502             if (nLastRow > nMaxY)
503                 nMaxY = nLastRow;
504         }
505     }
506 
507     if (nMaxX == MAXCOL)                    // Attribute rechts weglassen
508     {
509         --nMaxX;
510         while ( nMaxX>0 && aCol[nMaxX].IsVisibleAttrEqual(aCol[nMaxX+1]) )
511             --nMaxX;
512     }
513 
514     if ( nMaxX < nMaxDataX )
515     {
516         nMaxX = nMaxDataX;
517     }
518     else if ( nMaxX > nMaxDataX )
519     {
520         SCCOL nAttrStartX = nMaxDataX + 1;
521         while ( nAttrStartX < MAXCOL )
522         {
523             SCCOL nAttrEndX = nAttrStartX;
524             while ( nAttrEndX < MAXCOL && aCol[nAttrStartX].IsVisibleAttrEqual(aCol[nAttrEndX+1]) )
525                 ++nAttrEndX;
526             if ( nAttrEndX + 1 - nAttrStartX >= SC_COLUMNS_STOP )
527             {
528                 // found equally-formatted columns behind data -> stop before these columns
529                 nMaxX = nAttrStartX - 1;
530 
531                 // also don't include default-formatted columns before that
532                 SCROW nDummyRow;
533                 while ( nMaxX > nMaxDataX && !aCol[nMaxX].GetLastVisibleAttr( nDummyRow ) )
534                     --nMaxX;
535                 break;
536             }
537             nAttrStartX = nAttrEndX + 1;
538         }
539     }
540 
541     rEndCol = nMaxX;
542     rEndRow = nMaxY;
543     return bFound;
544 }
545 
GetPrintAreaHor(SCROW nStartRow,SCROW nEndRow,SCCOL & rEndCol,sal_Bool) const546 sal_Bool ScTable::GetPrintAreaHor( SCROW nStartRow, SCROW nEndRow,
547                                 SCCOL& rEndCol, sal_Bool /* bNotes */ ) const
548 {
549     sal_Bool bFound = sal_False;
550     SCCOL nMaxX = 0;
551     SCCOL i;
552 
553     for (i=0; i<=MAXCOL; i++)               // Attribute testen
554     {
555         if (aCol[i].HasVisibleAttrIn( nStartRow, nEndRow ))
556         {
557             bFound = sal_True;
558             nMaxX = i;
559         }
560     }
561 
562     if (nMaxX == MAXCOL)                    // Attribute rechts weglassen
563     {
564         --nMaxX;
565         while ( nMaxX>0 && aCol[nMaxX].IsVisibleAttrEqual(aCol[nMaxX+1], nStartRow, nEndRow) )
566             --nMaxX;
567     }
568 
569     for (i=0; i<=MAXCOL; i++)               // Daten testen
570     {
571         if (!aCol[i].IsEmptyBlock( nStartRow, nEndRow ))        //! bNotes ??????
572         {
573             bFound = sal_True;
574             if (i>nMaxX)
575                 nMaxX = i;
576         }
577     }
578 
579     rEndCol = nMaxX;
580     return bFound;
581 }
582 
GetPrintAreaVer(SCCOL nStartCol,SCCOL nEndCol,SCROW & rEndRow,sal_Bool bNotes) const583 sal_Bool ScTable::GetPrintAreaVer( SCCOL nStartCol, SCCOL nEndCol,
584                                 SCROW& rEndRow, sal_Bool bNotes ) const
585 {
586     sal_Bool bFound = sal_False;
587     SCROW nMaxY = 0;
588     SCCOL i;
589 
590     for (i=nStartCol; i<=nEndCol; i++)              // Attribute testen
591     {
592         SCROW nLastRow;
593         if (aCol[i].GetLastVisibleAttr( nLastRow ))
594         {
595             bFound = sal_True;
596             if (nLastRow > nMaxY)
597                 nMaxY = nLastRow;
598         }
599     }
600 
601     for (i=nStartCol; i<=nEndCol; i++)              // Daten testen
602         if (!aCol[i].IsEmptyVisData(bNotes))
603         {
604             bFound = sal_True;
605             SCROW nColY = aCol[i].GetLastVisDataPos(bNotes);
606             if (nColY > nMaxY)
607                 nMaxY = nColY;
608         }
609 
610     rEndRow = nMaxY;
611     return bFound;
612 }
613 
GetDataStart(SCCOL & rStartCol,SCROW & rStartRow) const614 sal_Bool ScTable::GetDataStart( SCCOL& rStartCol, SCROW& rStartRow ) const
615 {
616     sal_Bool bFound = sal_False;
617     SCCOL nMinX = MAXCOL;
618     SCROW nMinY = MAXROW;
619     SCCOL i;
620 
621     for (i=0; i<=MAXCOL; i++)                   // Attribute testen
622     {
623         SCROW nFirstRow;
624         if (aCol[i].GetFirstVisibleAttr( nFirstRow ))
625         {
626             if (!bFound)
627                 nMinX = i;
628             bFound = sal_True;
629             if (nFirstRow < nMinY)
630                 nMinY = nFirstRow;
631         }
632     }
633 
634     if (nMinX == 0)                                     // Attribute links weglassen
635     {
636         if ( aCol[0].IsVisibleAttrEqual(aCol[1]) )      // keine einzelnen
637         {
638             ++nMinX;
639             while ( nMinX<MAXCOL && aCol[nMinX].IsVisibleAttrEqual(aCol[nMinX-1]) )
640                 ++nMinX;
641         }
642     }
643 
644     sal_Bool bDatFound = sal_False;
645     for (i=0; i<=MAXCOL; i++)                   // Daten testen
646         if (!aCol[i].IsEmptyVisData(sal_True))
647         {
648             if (!bDatFound && i<nMinX)
649                 nMinX = i;
650             bFound = bDatFound = sal_True;
651             SCROW nColY = aCol[i].GetFirstVisDataPos(sal_True);
652             if (nColY < nMinY)
653                 nMinY = nColY;
654         }
655 
656     rStartCol = nMinX;
657     rStartRow = nMinY;
658     return bFound;
659 }
660 
GetDataArea(SCCOL & rStartCol,SCROW & rStartRow,SCCOL & rEndCol,SCROW & rEndRow,sal_Bool bIncludeOld,bool bOnlyDown) const661 void ScTable::GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow,
662                            sal_Bool bIncludeOld, bool bOnlyDown ) const
663 {
664     sal_Bool bLeft       = sal_False;
665     sal_Bool bRight  = sal_False;
666     sal_Bool bTop        = sal_False;
667     sal_Bool bBottom = sal_False;
668     sal_Bool bChanged;
669     sal_Bool bFound;
670     SCCOL i;
671     SCROW nTest;
672 
673     do
674     {
675         bChanged = sal_False;
676 
677         if (!bOnlyDown)
678         {
679             SCROW nStart = rStartRow;
680             SCROW nEnd = rEndRow;
681             if (nStart>0) --nStart;
682             if (nEnd<MAXROW) ++nEnd;
683 
684             if (rEndCol < MAXCOL)
685                 if (!aCol[rEndCol+1].IsEmptyBlock(nStart,nEnd))
686                 {
687                     ++rEndCol;
688                     bChanged = sal_True;
689                     bRight = sal_True;
690                 }
691 
692             if (rStartCol > 0)
693                 if (!aCol[rStartCol-1].IsEmptyBlock(nStart,nEnd))
694                 {
695                     --rStartCol;
696                     bChanged = sal_True;
697                     bLeft = sal_True;
698                 }
699 
700             if (rStartRow > 0)
701             {
702                 nTest = rStartRow-1;
703                 bFound = sal_False;
704                 for (i=rStartCol; i<=rEndCol && !bFound; i++)
705                     if (aCol[i].HasDataAt(nTest))
706                         bFound = sal_True;
707                 if (bFound)
708                 {
709                     --rStartRow;
710                     bChanged = sal_True;
711                     bTop = sal_True;
712                 }
713             }
714         }
715 
716         if (rEndRow < MAXROW)
717         {
718             nTest = rEndRow+1;
719             bFound = sal_False;
720             for (i=rStartCol; i<=rEndCol && !bFound; i++)
721                 if (aCol[i].HasDataAt(nTest))
722                     bFound = sal_True;
723             if (bFound)
724             {
725                 ++rEndRow;
726                 bChanged = sal_True;
727                 bBottom = sal_True;
728             }
729         }
730     }
731     while( bChanged );
732 
733     if ( !bIncludeOld )
734     {
735         if ( !bLeft && rStartCol < MAXCOL && rStartCol < rEndCol )
736             if ( aCol[rStartCol].IsEmptyBlock(rStartRow,rEndRow) )
737                 ++rStartCol;
738         if ( !bRight && rEndCol > 0 && rStartCol < rEndCol )
739             if ( aCol[rEndCol].IsEmptyBlock(rStartRow,rEndRow) )
740                 --rEndCol;
741         if ( !bTop && rStartRow < MAXROW && rStartRow < rEndRow )
742         {
743             bFound = sal_False;
744             for (i=rStartCol; i<=rEndCol && !bFound; i++)
745                 if (aCol[i].HasDataAt(rStartRow))
746                     bFound = sal_True;
747             if (!bFound)
748                 ++rStartRow;
749         }
750         if ( !bBottom && rEndRow > 0 && rStartRow < rEndRow )
751         {
752             bFound = sal_False;
753             for (i=rStartCol; i<=rEndCol && !bFound; i++)
754                 if (aCol[i].HasDataAt(rEndRow))
755                     bFound = sal_True;
756             if (!bFound)
757                 --rEndRow;
758         }
759     }
760 }
761 
762 
ShrinkToUsedDataArea(bool & o_bShrunk,SCCOL & rStartCol,SCROW & rStartRow,SCCOL & rEndCol,SCROW & rEndRow,bool bColumnsOnly) const763 bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow,
764         SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const
765 {
766     o_bShrunk = false;
767 
768     PutInOrder( rStartCol, rEndCol);
769     PutInOrder( rStartRow, rEndRow);
770     if (rStartCol < 0)
771         rStartCol = 0, o_bShrunk = true;
772     if (rStartRow < 0)
773         rStartRow = 0, o_bShrunk = true;
774     if (rEndCol > MAXCOL)
775         rEndCol = MAXCOL, o_bShrunk = true;
776     if (rEndRow > MAXROW)
777         rEndRow = MAXROW, o_bShrunk = true;
778 
779     bool bChanged;
780     do
781     {
782         bChanged = false;
783 
784         while (rStartCol < rEndCol)
785         {
786             if (aCol[rEndCol].IsEmptyBlock( rStartRow, rEndRow))
787             {
788                 --rEndCol;
789                 bChanged = true;
790             }
791             else
792                 break;  // while
793         }
794 
795         while (rStartCol < rEndCol)
796         {
797             if (aCol[rStartCol].IsEmptyBlock( rStartRow, rEndRow))
798             {
799                 ++rStartCol;
800                 bChanged = true;
801             }
802             else
803                 break;  // while
804         }
805 
806         if (!bColumnsOnly)
807         {
808             if (rStartRow < rEndRow)
809             {
810                 bool bFound = false;
811                 for (SCCOL i=rStartCol; i<=rEndCol && !bFound; i++)
812                     if (aCol[i].HasDataAt( rStartRow))
813                         bFound = true;
814                 if (!bFound)
815                 {
816                     ++rStartRow;
817                     bChanged = true;
818                 }
819             }
820 
821             if (rStartRow < rEndRow)
822             {
823                 bool bFound = false;
824                 for (SCCOL i=rStartCol; i<=rEndCol && !bFound; i++)
825                     if (aCol[i].HasDataAt( rEndRow))
826                         bFound = true;
827                 if (!bFound)
828                 {
829                     --rEndRow;
830                     bChanged = true;
831                 }
832             }
833         }
834 
835         if (bChanged)
836             o_bShrunk = true;
837     } while( bChanged );
838 
839     return rStartCol != rEndCol || (bColumnsOnly ?
840             !aCol[rStartCol].IsEmptyBlock( rStartRow, rEndRow) :
841             (rStartRow != rEndRow || aCol[rStartCol].HasDataAt( rStartRow)));
842 }
843 
844 
GetEmptyLinesInBlock(SCCOL nStartCol,SCROW nStartRow,SCCOL nEndCol,SCROW nEndRow,ScDirection eDir)845 SCSIZE ScTable::GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow,
846                                         SCCOL nEndCol, SCROW nEndRow, ScDirection eDir )
847 {
848     SCSIZE nCount = 0;
849     SCCOL nCol;
850     if ((eDir == DIR_BOTTOM) || (eDir == DIR_TOP))
851     {
852         nCount = static_cast<SCSIZE>(nEndRow - nStartRow);
853         for (nCol = nStartCol; nCol <= nEndCol; nCol++)
854             nCount = Min(nCount, aCol[nCol].GetEmptyLinesInBlock(nStartRow, nEndRow, eDir));
855     }
856     else if (eDir == DIR_RIGHT)
857     {
858         nCol = nEndCol;
859         while (((SCsCOL)nCol >= (SCsCOL)nStartCol) &&
860                  aCol[nCol].IsEmptyBlock(nStartRow, nEndRow))
861         {
862             nCount++;
863             nCol--;
864         }
865     }
866     else
867     {
868         nCol = nStartCol;
869         while ((nCol <= nEndCol) && aCol[nCol].IsEmptyBlock(nStartRow, nEndRow))
870         {
871             nCount++;
872             nCol++;
873         }
874     }
875     return nCount;
876 }
877 
IsEmptyLine(SCROW nRow,SCCOL nStartCol,SCCOL nEndCol)878 sal_Bool ScTable::IsEmptyLine( SCROW nRow, SCCOL nStartCol, SCCOL nEndCol )
879 {
880     sal_Bool bFound = sal_False;
881     for (SCCOL i=nStartCol; i<=nEndCol && !bFound; i++)
882         if (aCol[i].HasDataAt(nRow))
883             bFound = sal_True;
884     return !bFound;
885 }
886 
LimitChartArea(SCCOL & rStartCol,SCROW & rStartRow,SCCOL & rEndCol,SCROW & rEndRow)887 void ScTable::LimitChartArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow )
888 {
889     while ( rStartCol<rEndCol && aCol[rStartCol].IsEmptyBlock(rStartRow,rEndRow) )
890         ++rStartCol;
891 
892     while ( rStartCol<rEndCol && aCol[rEndCol].IsEmptyBlock(rStartRow,rEndRow) )
893         --rEndCol;
894 
895     while ( rStartRow<rEndRow && IsEmptyLine(rStartRow, rStartCol, rEndCol) )
896         ++rStartRow;
897 
898     while ( rStartRow<rEndRow && IsEmptyLine(rEndRow, rStartCol, rEndCol) )
899         --rEndRow;
900 }
901 
FindAreaPos(SCCOL & rCol,SCROW & rRow,SCsCOL nMovX,SCsROW nMovY)902 void ScTable::FindAreaPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY )
903 {
904     if (nMovX)
905     {
906         SCsCOL nNewCol = (SCsCOL) rCol;
907         sal_Bool bThere = aCol[nNewCol].HasVisibleDataAt(rRow);
908         sal_Bool bFnd;
909         if (bThere)
910         {
911             do
912             {
913                 nNewCol = sal::static_int_cast<SCsCOL>( nNewCol + nMovX );
914                 bFnd = (nNewCol>=0 && nNewCol<=MAXCOL) ? aCol[nNewCol].HasVisibleDataAt(rRow) : sal_False;
915             }
916             while (bFnd);
917             nNewCol = sal::static_int_cast<SCsCOL>( nNewCol - nMovX );
918 
919             if (nNewCol == (SCsCOL)rCol)
920                 bThere = sal_False;
921         }
922 
923         if (!bThere)
924         {
925             do
926             {
927                 nNewCol = sal::static_int_cast<SCsCOL>( nNewCol + nMovX );
928                 bFnd = (nNewCol>=0 && nNewCol<=MAXCOL) ? aCol[nNewCol].HasVisibleDataAt(rRow) : sal_True;
929             }
930             while (!bFnd);
931         }
932 
933         if (nNewCol<0) nNewCol=0;
934         if (nNewCol>MAXCOL) nNewCol=MAXCOL;
935         rCol = (SCCOL) nNewCol;
936     }
937 
938     if (nMovY)
939         aCol[rCol].FindDataAreaPos(rRow,nMovY);
940 }
941 
ValidNextPos(SCCOL nCol,SCROW nRow,const ScMarkData & rMark,sal_Bool bMarked,sal_Bool bUnprotected)942 sal_Bool ScTable::ValidNextPos( SCCOL nCol, SCROW nRow, const ScMarkData& rMark,
943                                 sal_Bool bMarked, sal_Bool bUnprotected )
944 {
945     if (!ValidCol(nCol) || !ValidRow(nRow))
946         return sal_False;
947 
948     if (pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED))
949         // Skip an overlapped cell.
950         return false;
951 
952     if (bMarked && !rMark.IsCellMarked(nCol,nRow))
953         return sal_False;
954 
955     if (bUnprotected && ((const ScProtectionAttr*)
956                         GetAttr(nCol,nRow,ATTR_PROTECTION))->GetProtection())
957         return sal_False;
958 
959     if (bMarked || bUnprotected)        //! auch sonst ???
960     {
961         //  #53697# ausgeblendete muessen uebersprungen werden, weil der Cursor sonst
962         //  auf der naechsten Zelle landet, auch wenn die geschuetzt/nicht markiert ist.
963         //! per Extra-Parameter steuern, nur fuer Cursor-Bewegung ???
964 
965         if (RowHidden(nRow))
966             return sal_False;
967 
968         if (ColHidden(nCol))
969             return sal_False;
970     }
971 
972     return sal_True;
973 }
974 
GetNextPos(SCCOL & rCol,SCROW & rRow,SCsCOL nMovX,SCsROW nMovY,sal_Bool bMarked,sal_Bool bUnprotected,const ScMarkData & rMark)975 void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
976                                 sal_Bool bMarked, sal_Bool bUnprotected, const ScMarkData& rMark )
977 {
978     if (bUnprotected && !IsProtected())     // Tabelle ueberhaupt geschuetzt?
979         bUnprotected = sal_False;
980 
981     sal_uInt16 nWrap = 0;
982     SCsCOL nCol = rCol;
983     SCsROW nRow = rRow;
984 
985     nCol = sal::static_int_cast<SCsCOL>( nCol + nMovX );
986     nRow = sal::static_int_cast<SCsROW>( nRow + nMovY );
987 
988     DBG_ASSERT( !nMovY || !bUnprotected,
989                 "GetNextPos mit bUnprotected horizontal nicht implementiert" );
990 
991     if ( nMovY && bMarked )
992     {
993         sal_Bool bUp = ( nMovY < 0 );
994         nRow = rMark.GetNextMarked( nCol, nRow, bUp );
995         while ( VALIDROW(nRow) &&
996                 (RowHidden(nRow) || pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
997         {
998             //  #53697# ausgeblendete ueberspringen (s.o.)
999             nRow += nMovY;
1000             nRow = rMark.GetNextMarked( nCol, nRow, bUp );
1001         }
1002 
1003         while ( nRow < 0 || nRow > MAXROW )
1004         {
1005             nCol = sal::static_int_cast<SCsCOL>( nCol + static_cast<SCsCOL>(nMovY) );
1006             while ( VALIDCOL(nCol) && ColHidden(nCol) )
1007                 nCol = sal::static_int_cast<SCsCOL>( nCol + static_cast<SCsCOL>(nMovY) );   //  #53697# skip hidden rows (see above)
1008             if (nCol < 0)
1009             {
1010                 nCol = MAXCOL;
1011                 if (++nWrap >= 2)
1012                     return;
1013             }
1014             else if (nCol > MAXCOL)
1015             {
1016                 nCol = 0;
1017                 if (++nWrap >= 2)
1018                     return;
1019             }
1020             if (nRow < 0)
1021                 nRow = MAXROW;
1022             else if (nRow > MAXROW)
1023                 nRow = 0;
1024             nRow = rMark.GetNextMarked( nCol, nRow, bUp );
1025             while ( VALIDROW(nRow) &&
1026                     (RowHidden(nRow) || pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
1027             {
1028                 //  #53697# ausgeblendete ueberspringen (s.o.)
1029                 nRow += nMovY;
1030                 nRow = rMark.GetNextMarked( nCol, nRow, bUp );
1031             }
1032         }
1033     }
1034 
1035     if ( nMovX && ( bMarked || bUnprotected ) )
1036     {
1037         // initiales Weiterzaehlen wrappen:
1038         if (nCol<0)
1039         {
1040             nCol = MAXCOL;
1041             --nRow;
1042             if (nRow<0)
1043                 nRow = MAXROW;
1044         }
1045         if (nCol>MAXCOL)
1046         {
1047             nCol = 0;
1048             ++nRow;
1049             if (nRow>MAXROW)
1050                 nRow = 0;
1051         }
1052 
1053         if ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) )
1054         {
1055             SCsROW* pNextRows = new SCsROW[MAXCOL+1];
1056             SCCOL i;
1057 
1058             if ( nMovX > 0 )                            //  vorwaerts
1059             {
1060                 for (i=0; i<=MAXCOL; i++)
1061                     pNextRows[i] = (i<nCol) ? (nRow+1) : nRow;
1062                 do
1063                 {
1064                     SCsROW nNextRow = pNextRows[nCol] + 1;
1065                     if ( bMarked )
1066                         nNextRow = rMark.GetNextMarked( nCol, nNextRow, sal_False );
1067                     if ( bUnprotected )
1068                         nNextRow = aCol[nCol].GetNextUnprotected( nNextRow, sal_False );
1069                     pNextRows[nCol] = nNextRow;
1070 
1071                     SCsROW nMinRow = MAXROW+1;
1072                     for (i=0; i<=MAXCOL; i++)
1073                         if (pNextRows[i] < nMinRow)     // bei gleichen den linken
1074                         {
1075                             nMinRow = pNextRows[i];
1076                             nCol = i;
1077                         }
1078                     nRow = nMinRow;
1079 
1080                     if ( nRow > MAXROW )
1081                     {
1082                         if (++nWrap >= 2) break;        // ungueltigen Wert behalten
1083                         nCol = 0;
1084                         nRow = 0;
1085                         for (i=0; i<=MAXCOL; i++)
1086                             pNextRows[i] = 0;           // alles ganz von vorne
1087                     }
1088                 }
1089                 while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
1090             }
1091             else                                        //  rueckwaerts
1092             {
1093                 for (i=0; i<=MAXCOL; i++)
1094                     pNextRows[i] = (i>nCol) ? (nRow-1) : nRow;
1095                 do
1096                 {
1097                     SCsROW nNextRow = pNextRows[nCol] - 1;
1098                     if ( bMarked )
1099                         nNextRow = rMark.GetNextMarked( nCol, nNextRow, sal_True );
1100                     if ( bUnprotected )
1101                         nNextRow = aCol[nCol].GetNextUnprotected( nNextRow, sal_True );
1102                     pNextRows[nCol] = nNextRow;
1103 
1104                     SCsROW nMaxRow = -1;
1105                     for (i=0; i<=MAXCOL; i++)
1106                         if (pNextRows[i] >= nMaxRow)    // bei gleichen den rechten
1107                         {
1108                             nMaxRow = pNextRows[i];
1109                             nCol = i;
1110                         }
1111                     nRow = nMaxRow;
1112 
1113                     if ( nRow < 0 )
1114                     {
1115                         if (++nWrap >= 2) break;        // ungueltigen Wert behalten
1116                         nCol = MAXCOL;
1117                         nRow = MAXROW;
1118                         for (i=0; i<=MAXCOL; i++)
1119                             pNextRows[i] = MAXROW;      // alles ganz von vorne
1120                     }
1121                 }
1122                 while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
1123             }
1124 
1125             delete[] pNextRows;
1126         }
1127     }
1128 
1129     //  ungueltige Werte kommen z.b. bei Tab heraus,
1130     //  wenn nicht markiert und nicht geschuetzt ist (linker / rechter Rand),
1131     //  dann Werte unveraendert lassen
1132 
1133     if (VALIDCOLROW(nCol,nRow))
1134     {
1135         rCol = nCol;
1136         rRow = nRow;
1137     }
1138 }
1139 
GetNextMarkedCell(SCCOL & rCol,SCROW & rRow,const ScMarkData & rMark)1140 sal_Bool ScTable::GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, const ScMarkData& rMark )
1141 {
1142     const ScMarkArray* pMarkArray = rMark.GetArray();
1143     DBG_ASSERT(pMarkArray,"GetNextMarkedCell ohne MarkArray");
1144     if ( !pMarkArray )
1145         return sal_False;
1146 
1147     ++rRow;                 // naechste Zelle ist gesucht
1148 
1149     while ( rCol <= MAXCOL )
1150     {
1151         const ScMarkArray& rArray = pMarkArray[rCol];
1152         while ( rRow <= MAXROW )
1153         {
1154             SCROW nStart = (SCROW) rArray.GetNextMarked( (SCsROW) rRow, sal_False );
1155             if ( nStart <= MAXROW )
1156             {
1157                 SCROW nEnd = rArray.GetMarkEnd( nStart, sal_False );
1158                 ScColumnIterator aColIter( &aCol[rCol], nStart, nEnd );
1159                 SCROW nCellRow;
1160                 ScBaseCell* pCell = NULL;
1161                 while ( aColIter.Next( nCellRow, pCell ) )
1162                 {
1163                     if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE )
1164                     {
1165                         rRow = nCellRow;
1166                         return sal_True;            // Zelle gefunden
1167                     }
1168                 }
1169                 rRow = nEnd + 1;                // naechsten markierten Bereich suchen
1170             }
1171             else
1172                 rRow = MAXROW + 1;              // Ende der Spalte
1173         }
1174         rRow = 0;
1175         ++rCol;                                 // naechste Spalte testen
1176     }
1177 
1178     return sal_False;                               // alle Spalten durch
1179 }
1180 
UpdateDrawRef(UpdateRefMode eUpdateRefMode,SCCOL nCol1,SCROW nRow1,SCTAB nTab1,SCCOL nCol2,SCROW nRow2,SCTAB nTab2,SCsCOL nDx,SCsROW nDy,SCsTAB nDz,bool bUpdateNoteCaptionPos)1181 void ScTable::UpdateDrawRef( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1182                                     SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
1183                                     SCsCOL nDx, SCsROW nDy, SCsTAB nDz, bool bUpdateNoteCaptionPos )
1184 {
1185     if ( nTab >= nTab1 && nTab <= nTab2 && nDz == 0 )       // only within the table
1186     {
1187         InitializeNoteCaptions();
1188         ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
1189         if ( eUpdateRefMode != URM_COPY && pDrawLayer )
1190         {
1191             if ( eUpdateRefMode == URM_MOVE )
1192             {                                               // source range
1193                 nCol1 = sal::static_int_cast<SCCOL>( nCol1 - nDx );
1194                 nRow1 = sal::static_int_cast<SCROW>( nRow1 - nDy );
1195                 nCol2 = sal::static_int_cast<SCCOL>( nCol2 - nDx );
1196                 nRow2 = sal::static_int_cast<SCROW>( nRow2 - nDy );
1197             }
1198             pDrawLayer->MoveArea( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy,
1199                                     (eUpdateRefMode == URM_INSDEL), bUpdateNoteCaptionPos );
1200         }
1201     }
1202 }
1203 
UpdateReference(UpdateRefMode eUpdateRefMode,SCCOL nCol1,SCROW nRow1,SCTAB nTab1,SCCOL nCol2,SCROW nRow2,SCTAB nTab2,SCsCOL nDx,SCsROW nDy,SCsTAB nDz,ScDocument * pUndoDoc,sal_Bool bIncludeDraw,bool bUpdateNoteCaptionPos)1204 void ScTable::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1205                      SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
1206                      ScDocument* pUndoDoc, sal_Bool bIncludeDraw, bool bUpdateNoteCaptionPos )
1207 {
1208     SCCOL i;
1209     SCCOL iMax;
1210     if ( eUpdateRefMode == URM_COPY )
1211     {
1212         i = nCol1;
1213         iMax = nCol2;
1214     }
1215     else
1216     {
1217         i = 0;
1218         iMax = MAXCOL;
1219     }
1220     for ( ; i<=iMax; i++)
1221         aCol[i].UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
1222                                     nDx, nDy, nDz, pUndoDoc );
1223 
1224     if ( bIncludeDraw )
1225         UpdateDrawRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz, bUpdateNoteCaptionPos );
1226 
1227     if ( nTab >= nTab1 && nTab <= nTab2 && nDz == 0 )       // print ranges: only within the table
1228     {
1229         SCTAB nSTab = nTab;
1230         SCTAB nETab = nTab;
1231         SCCOL nSCol = 0;
1232         SCROW nSRow = 0;
1233         SCCOL nECol = 0;
1234         SCROW nERow = 0;
1235         sal_Bool bRecalcPages = sal_False;
1236 
1237         for ( ScRangeVec::iterator aIt = aPrintRanges.begin(), aEnd = aPrintRanges.end(); aIt != aEnd; ++aIt )
1238         {
1239             nSCol = aIt->aStart.Col();
1240             nSRow = aIt->aStart.Row();
1241             nECol = aIt->aEnd.Col();
1242             nERow = aIt->aEnd.Row();
1243 
1244             // do not try to modify sheet index of print range
1245             if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
1246                                       nCol1,nRow1,nTab, nCol2,nRow2,nTab,
1247                                       nDx,nDy,0,
1248                                       nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
1249             {
1250                 *aIt = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
1251                 bRecalcPages = sal_True;
1252             }
1253         }
1254 
1255         if ( pRepeatColRange )
1256         {
1257             nSCol = pRepeatColRange->aStart.Col();
1258             nSRow = pRepeatColRange->aStart.Row();
1259             nECol = pRepeatColRange->aEnd.Col();
1260             nERow = pRepeatColRange->aEnd.Row();
1261 
1262             // do not try to modify sheet index of repeat range
1263             if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
1264                                       nCol1,nRow1,nTab, nCol2,nRow2,nTab,
1265                                       nDx,nDy,0,
1266                                       nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
1267             {
1268                 *pRepeatColRange = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
1269                 bRecalcPages = sal_True;
1270                 nRepeatStartX = nSCol;  // fuer UpdatePageBreaks
1271                 nRepeatEndX = nECol;
1272             }
1273         }
1274 
1275         if ( pRepeatRowRange )
1276         {
1277             nSCol = pRepeatRowRange->aStart.Col();
1278             nSRow = pRepeatRowRange->aStart.Row();
1279             nECol = pRepeatRowRange->aEnd.Col();
1280             nERow = pRepeatRowRange->aEnd.Row();
1281 
1282             // do not try to modify sheet index of repeat range
1283             if ( ScRefUpdate::Update( pDocument, eUpdateRefMode,
1284                                       nCol1,nRow1,nTab, nCol2,nRow2,nTab,
1285                                       nDx,nDy,0,
1286                                       nSCol,nSRow,nSTab, nECol,nERow,nETab ) )
1287             {
1288                 *pRepeatRowRange = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
1289                 bRecalcPages = sal_True;
1290                 nRepeatStartY = nSRow;  // fuer UpdatePageBreaks
1291                 nRepeatEndY = nERow;
1292             }
1293         }
1294 
1295         //  updating print ranges is not necessary with multiple print ranges
1296         if ( bRecalcPages && GetPrintRangeCount() <= 1 )
1297         {
1298             UpdatePageBreaks(NULL);
1299 
1300             pDocument->RepaintRange( ScRange(0,0,nTab,MAXCOL,MAXROW,nTab) );
1301         }
1302     }
1303 }
1304 
UpdateTranspose(const ScRange & rSource,const ScAddress & rDest,ScDocument * pUndoDoc)1305 void ScTable::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
1306                                     ScDocument* pUndoDoc )
1307 {
1308     for ( SCCOL i=0; i<=MAXCOL; i++ )
1309         aCol[i].UpdateTranspose( rSource, rDest, pUndoDoc );
1310 }
1311 
UpdateGrow(const ScRange & rArea,SCCOL nGrowX,SCROW nGrowY)1312 void ScTable::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
1313 {
1314     for ( SCCOL i=0; i<=MAXCOL; i++ )
1315         aCol[i].UpdateGrow( rArea, nGrowX, nGrowY );
1316 }
1317 
UpdateInsertTab(SCTAB nTable)1318 void ScTable::UpdateInsertTab(SCTAB nTable)
1319 {
1320     if (nTab >= nTable) nTab++;
1321     for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].UpdateInsertTab(nTable);
1322 
1323     if (IsStreamValid())
1324         SetStreamValid(sal_False);
1325 }
1326 
1327 //UNUSED2008-05  void ScTable::UpdateInsertTabOnlyCells(SCTAB nTable)
1328 //UNUSED2008-05  {
1329 //UNUSED2008-05      for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].UpdateInsertTabOnlyCells(nTable);
1330 //UNUSED2008-05  }
1331 
UpdateDeleteTab(SCTAB nTable,sal_Bool bIsMove,ScTable * pRefUndo)1332 void ScTable::UpdateDeleteTab( SCTAB nTable, sal_Bool bIsMove, ScTable* pRefUndo )
1333 {
1334     if (nTab > nTable) nTab--;
1335 
1336     SCCOL i;
1337     if (pRefUndo)
1338         for (i=0; i <= MAXCOL; i++) aCol[i].UpdateDeleteTab(nTable, bIsMove, &pRefUndo->aCol[i]);
1339     else
1340         for (i=0; i <= MAXCOL; i++) aCol[i].UpdateDeleteTab(nTable, bIsMove, NULL);
1341 
1342     if (IsStreamValid())
1343         SetStreamValid(sal_False);
1344 }
1345 
UpdateMoveTab(SCTAB nOldPos,SCTAB nNewPos,SCTAB nTabNo,ScProgress & rProgress)1346 void ScTable::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo,
1347         ScProgress& rProgress )
1348 {
1349     nTab = nTabNo;
1350     for ( SCCOL i=0; i <= MAXCOL; i++ )
1351     {
1352         aCol[i].UpdateMoveTab( nOldPos, nNewPos, nTabNo );
1353         rProgress.SetState( rProgress.GetState() + aCol[i].GetCodeCount() );
1354     }
1355 
1356     if (IsStreamValid())
1357         SetStreamValid(sal_False);
1358 }
1359 
UpdateCompile(sal_Bool bForceIfNameInUse)1360 void ScTable::UpdateCompile( sal_Bool bForceIfNameInUse )
1361 {
1362     for (SCCOL i=0; i <= MAXCOL; i++)
1363     {
1364         aCol[i].UpdateCompile( bForceIfNameInUse );
1365     }
1366 }
1367 
SetTabNo(SCTAB nNewTab)1368 void ScTable::SetTabNo(SCTAB nNewTab)
1369 {
1370     nTab = nNewTab;
1371     for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].SetTabNo(nNewTab);
1372 }
1373 
IsRangeNameInUse(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,sal_uInt16 nIndex) const1374 sal_Bool ScTable::IsRangeNameInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1375                                sal_uInt16 nIndex) const
1376 {
1377     sal_Bool bInUse = sal_False;
1378     for (SCCOL i = nCol1; !bInUse && (i <= nCol2) && (ValidCol(i)); i++)
1379         bInUse = aCol[i].IsRangeNameInUse(nRow1, nRow2, nIndex);
1380     return bInUse;
1381 }
1382 
FindRangeNamesInUse(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,std::set<sal_uInt16> & rIndexes) const1383 void ScTable::FindRangeNamesInUse(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1384                                std::set<sal_uInt16>& rIndexes) const
1385 {
1386     for (SCCOL i = nCol1; i <= nCol2 && ValidCol(i); i++)
1387         aCol[i].FindRangeNamesInUse(nRow1, nRow2, rIndexes);
1388 }
1389 
ReplaceRangeNamesInUse(SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,const ScRangeData::IndexMap & rMap)1390 void ScTable::ReplaceRangeNamesInUse(SCCOL nCol1, SCROW nRow1,
1391                                     SCCOL nCol2, SCROW nRow2,
1392                                     const ScRangeData::IndexMap& rMap )
1393 {
1394     for (SCCOL i = nCol1; i <= nCol2 && (ValidCol(i)); i++)
1395     {
1396         aCol[i].ReplaceRangeNamesInUse( nRow1, nRow2, rMap );
1397     }
1398 }
1399 
ExtendPrintArea(OutputDevice * pDev,SCCOL,SCROW nStartRow,SCCOL & rEndCol,SCROW nEndRow)1400 void ScTable::ExtendPrintArea( OutputDevice* pDev,
1401                     SCCOL /* nStartCol */, SCROW nStartRow, SCCOL& rEndCol, SCROW nEndRow )
1402 {
1403     if ( !pColFlags || !pRowFlags )
1404     {
1405         DBG_ERROR("keine ColInfo oder RowInfo in ExtendPrintArea");
1406         return;
1407     }
1408 
1409     Point aPix1000 = pDev->LogicToPixel( Point(1000,1000), MAP_TWIP );
1410     double nPPTX = aPix1000.X() / 1000.0;
1411     double nPPTY = aPix1000.Y() / 1000.0;
1412 
1413     // First, mark those columns that we need to skip i.e. hidden and empty columns.
1414 
1415     ScFlatBoolColSegments aSkipCols;
1416     aSkipCols.setInsertFromBack(true); // speed optimazation.
1417     aSkipCols.setFalse(0, MAXCOL);
1418     for (SCCOL i = 0; i <= MAXCOL; ++i)
1419     {
1420         SCCOL nLastCol = i;
1421         if (ColHidden(i, NULL, &nLastCol))
1422         {
1423             // Columns are hidden in this range.
1424             aSkipCols.setTrue(i, nLastCol);
1425         }
1426         else
1427         {
1428             // These columns are visible.  Check for empty columns.
1429             for (SCCOL j = i; j <= nLastCol; ++j)
1430             {
1431                 if (aCol[j].GetCellCount() == 0)
1432                     // empty
1433                     aSkipCols.setTrue(j,j);
1434             }
1435         }
1436         i = nLastCol;
1437     }
1438 
1439     ScFlatBoolColSegments::RangeData aColData;
1440     for (SCCOL nCol = rEndCol; nCol >= 0; --nCol)
1441     {
1442         if (!aSkipCols.getRangeData(nCol, aColData))
1443             // Failed to get the data.  This should never happen!
1444             return;
1445 
1446         if (aColData.mbValue)
1447         {
1448             // Skip these columns.
1449             nCol = aColData.mnCol1; // move toward 0.
1450             continue;
1451         }
1452 
1453         // These are visible and non-empty columns.
1454         for (SCCOL nDataCol = nCol; 0 <= nDataCol && nDataCol >= aColData.mnCol1; --nDataCol)
1455         {
1456             SCCOL nPrintCol = nDataCol;
1457             VisibleDataCellIterator aIter(*mpHiddenRows, aCol[nDataCol]);
1458             ScBaseCell* pCell = aIter.reset(nStartRow);
1459             if (!pCell)
1460                 // No visible cells found in this column.  Skip it.
1461                 continue;
1462 
1463             while (pCell)
1464             {
1465                 SCCOL nNewCol = nDataCol;
1466                 SCROW nRow = aIter.getRow();
1467                 if (nRow > nEndRow)
1468                     // Went past the last row position.  Bail out.
1469                     break;
1470 
1471                 MaybeAddExtraColumn(nNewCol, nRow, pDev, nPPTX, nPPTY);
1472                 if (nNewCol > nPrintCol)
1473                     nPrintCol = nNewCol;
1474                 pCell = aIter.next();
1475             }
1476 
1477             if (nPrintCol > rEndCol)
1478                 // Make sure we don't shrink the print area.
1479                 rEndCol = nPrintCol;
1480         }
1481         nCol = aColData.mnCol1; // move toward 0.
1482     }
1483 }
1484 
MaybeAddExtraColumn(SCCOL & rCol,SCROW nRow,OutputDevice * pDev,double nPPTX,double nPPTY)1485 void ScTable::MaybeAddExtraColumn(SCCOL& rCol, SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY)
1486 {
1487     ScBaseCell* pCell = aCol[rCol].GetCell(nRow);
1488     if (!pCell || !pCell->HasStringData())
1489         return;
1490 
1491     bool bFormula = false;  //! ueberge
1492     long nPixel = pCell->GetTextWidth();
1493 
1494     // Breite bereits im Idle-Handler berechnet?
1495     if ( TEXTWIDTH_DIRTY == nPixel )
1496     {
1497         ScNeededSizeOptions aOptions;
1498         aOptions.bTotalSize  = sal_True;
1499         aOptions.bFormula    = bFormula;
1500         aOptions.bSkipMerged = sal_False;
1501 
1502         Fraction aZoom(1,1);
1503         nPixel = aCol[rCol].GetNeededSize(
1504             nRow, pDev, nPPTX, nPPTY, aZoom, aZoom, true, aOptions );
1505         pCell->SetTextWidth( (sal_uInt16)nPixel );
1506     }
1507 
1508     long nTwips = (long) (nPixel / nPPTX);
1509     long nDocW = GetColWidth( rCol );
1510 
1511     long nMissing = nTwips - nDocW;
1512     if ( nMissing > 0 )
1513     {
1514         //  look at alignment
1515 
1516         const ScPatternAttr* pPattern = GetPattern( rCol, nRow );
1517         const SfxItemSet* pCondSet = NULL;
1518         if ( ((const SfxUInt32Item&)pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() )
1519             pCondSet = pDocument->GetCondResult( rCol, nRow, nTab );
1520 
1521         SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
1522                         pPattern->GetItem( ATTR_HOR_JUSTIFY, pCondSet )).GetValue();
1523         if ( eHorJust == SVX_HOR_JUSTIFY_CENTER )
1524             nMissing /= 2;                          // distributed into both directions
1525         else
1526         {
1527             // STANDARD is LEFT (only text is handled here)
1528             bool bRight = ( eHorJust == SVX_HOR_JUSTIFY_RIGHT );
1529             if ( IsLayoutRTL() )
1530                 bRight = !bRight;
1531             if ( bRight )
1532                 nMissing = 0;       // extended only to the left (logical)
1533         }
1534     }
1535 
1536     SCCOL nNewCol = rCol;
1537     while (nMissing > 0 && nNewCol < MAXCOL)
1538     {
1539         ScBaseCell* pNextCell = aCol[nNewCol+1].GetCell(nRow);
1540         if (pNextCell && pNextCell->GetCellType() != CELLTYPE_NOTE)
1541             // Cell content in a next column ends display of this string.
1542             nMissing = 0;
1543         else
1544             nMissing -= GetColWidth(++nNewCol);
1545     }
1546     rCol = nNewCol;
1547 }
1548 
DoColResize(SCCOL nCol1,SCCOL nCol2,SCSIZE nAdd)1549 void ScTable::DoColResize( SCCOL nCol1, SCCOL nCol2, SCSIZE nAdd )
1550 {
1551     for (SCCOL nCol=nCol1; nCol<=nCol2; nCol++)
1552         aCol[nCol].Resize(aCol[nCol].GetCellCount() + nAdd);
1553 }
1554 
1555 #define SET_PRINTRANGE( p1, p2 ) \
1556     if ( (p2) )                             \
1557     {                                       \
1558         if ( (p1) )                         \
1559             *(p1) = *(p2);                  \
1560         else                                \
1561             (p1) = new ScRange( *(p2) );    \
1562     }                                       \
1563     else                                    \
1564         DELETEZ( (p1) )
1565 
SetRepeatColRange(const ScRange * pNew)1566 void ScTable::SetRepeatColRange( const ScRange* pNew )
1567 {
1568     SET_PRINTRANGE( pRepeatColRange, pNew );
1569 
1570     if (IsStreamValid())
1571         SetStreamValid(sal_False);
1572 }
1573 
SetRepeatRowRange(const ScRange * pNew)1574 void ScTable::SetRepeatRowRange( const ScRange* pNew )
1575 {
1576     SET_PRINTRANGE( pRepeatRowRange, pNew );
1577 
1578     if (IsStreamValid())
1579         SetStreamValid(sal_False);
1580 }
1581 
ClearPrintRanges()1582 void ScTable::ClearPrintRanges()
1583 {
1584     aPrintRanges.clear();
1585     bPrintEntireSheet = sal_False;
1586     InvalidatePageBreaks();     // #i117952# forget page breaks for an old print range
1587 
1588     if (IsStreamValid())
1589         SetStreamValid(sal_False);
1590 }
1591 
AddPrintRange(const ScRange & rNew)1592 void ScTable::AddPrintRange( const ScRange& rNew )
1593 {
1594     bPrintEntireSheet = sal_False;
1595     if( aPrintRanges.size() < 0xFFFF )
1596         aPrintRanges.push_back( rNew );
1597 
1598     if (IsStreamValid())
1599         SetStreamValid(sal_False);
1600 }
1601 
1602 //UNUSED2009-05 void ScTable::SetPrintRange( const ScRange& rNew )
1603 //UNUSED2009-05 {
1604 //UNUSED2009-05     ClearPrintRanges();
1605 //UNUSED2009-05     AddPrintRange( rNew );
1606 //UNUSED2009-05 }
1607 
SetPrintEntireSheet()1608 void ScTable::SetPrintEntireSheet()
1609 {
1610     if( !IsPrintEntireSheet() )
1611     {
1612         ClearPrintRanges();
1613         bPrintEntireSheet = sal_True;
1614     }
1615 }
1616 
GetPrintRange(sal_uInt16 nPos) const1617 const ScRange* ScTable::GetPrintRange(sal_uInt16 nPos) const
1618 {
1619     return (nPos < GetPrintRangeCount()) ? &aPrintRanges[ nPos ] : NULL;
1620 }
1621 
FillPrintSaver(ScPrintSaverTab & rSaveTab) const1622 void ScTable::FillPrintSaver( ScPrintSaverTab& rSaveTab ) const
1623 {
1624     rSaveTab.SetAreas( aPrintRanges, bPrintEntireSheet );
1625     rSaveTab.SetRepeat( pRepeatColRange, pRepeatRowRange );
1626 }
1627 
RestorePrintRanges(const ScPrintSaverTab & rSaveTab)1628 void ScTable::RestorePrintRanges( const ScPrintSaverTab& rSaveTab )
1629 {
1630     aPrintRanges = rSaveTab.GetPrintRanges();
1631     bPrintEntireSheet = rSaveTab.IsEntireSheet();
1632     SetRepeatColRange( rSaveTab.GetRepeatCol() );
1633     SetRepeatRowRange( rSaveTab.GetRepeatRow() );
1634 
1635     InvalidatePageBreaks();     // #i117952# forget page breaks for an old print range
1636     UpdatePageBreaks(NULL);
1637 }
1638 
1639 SCROW ScTable::VisibleDataCellIterator::ROW_NOT_FOUND = -1;
1640 
VisibleDataCellIterator(ScFlatBoolRowSegments & rRowSegs,ScColumn & rColumn)1641 ScTable::VisibleDataCellIterator::VisibleDataCellIterator(ScFlatBoolRowSegments& rRowSegs, ScColumn& rColumn) :
1642     mrRowSegs(rRowSegs),
1643     mrColumn(rColumn),
1644     mpCell(NULL),
1645     mnCurRow(ROW_NOT_FOUND),
1646     mnUBound(ROW_NOT_FOUND)
1647 {
1648 }
1649 
~VisibleDataCellIterator()1650 ScTable::VisibleDataCellIterator::~VisibleDataCellIterator()
1651 {
1652 }
1653 
reset(SCROW nRow)1654 ScBaseCell* ScTable::VisibleDataCellIterator::reset(SCROW nRow)
1655 {
1656     if (nRow > MAXROW)
1657     {
1658         mnCurRow = ROW_NOT_FOUND;
1659         return NULL;
1660     }
1661 
1662     ScFlatBoolRowSegments::RangeData aData;
1663     if (!mrRowSegs.getRangeData(nRow, aData))
1664     {
1665         mnCurRow = ROW_NOT_FOUND;
1666         return NULL;
1667     }
1668 
1669     if (!aData.mbValue)
1670     {
1671         // specified row is visible.  Take it.
1672         mnCurRow = nRow;
1673         mnUBound = aData.mnRow2;
1674     }
1675     else
1676     {
1677         // specified row is not-visible.  The first visible row is the start of
1678         // the next segment.
1679         mnCurRow = aData.mnRow2 + 1;
1680         mnUBound = mnCurRow; // get range data on the next iteration.
1681         if (mnCurRow > MAXROW)
1682         {
1683             // Make sure the row doesn't exceed our current limit.
1684             mnCurRow = ROW_NOT_FOUND;
1685             return NULL;
1686         }
1687     }
1688 
1689     mpCell = mrColumn.GetCell(mnCurRow);
1690     if (mpCell)
1691         // First visible cell found.
1692         return mpCell;
1693 
1694     // Find a first visible cell below this row (if any).
1695     return next();
1696 }
1697 
next()1698 ScBaseCell* ScTable::VisibleDataCellIterator::next()
1699 {
1700     if (mnCurRow == ROW_NOT_FOUND)
1701         return NULL;
1702 
1703     while (mrColumn.GetNextDataPos(mnCurRow))
1704     {
1705         if (mnCurRow > mnUBound)
1706         {
1707             // We don't know the visibility of this row range.  Query it.
1708             ScFlatBoolRowSegments::RangeData aData;
1709             if (!mrRowSegs.getRangeData(mnCurRow, aData))
1710             {
1711                 mnCurRow = ROW_NOT_FOUND;
1712                 return NULL;
1713             }
1714 
1715             if (aData.mbValue)
1716             {
1717                 // This row is invisible.  Skip to the last invisible row and
1718                 // try again.
1719                 mnCurRow = mnUBound = aData.mnRow2;
1720                 continue;
1721             }
1722 
1723             // This row is visible.
1724             mnUBound = aData.mnRow2;
1725         }
1726 
1727         mpCell = mrColumn.GetCell(mnCurRow);
1728         if (mpCell)
1729             return mpCell;
1730     }
1731     mnCurRow = ROW_NOT_FOUND;
1732     return NULL;
1733 }
1734 
getRow() const1735 SCROW ScTable::VisibleDataCellIterator::getRow() const
1736 {
1737     return mnCurRow;
1738 }
1739 
1740