xref: /aoo4110/main/sc/source/core/data/table1.cxx (revision b1cdbd2c)
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