xref: /aoo42x/main/sc/source/core/data/table5.cxx (revision dcafab4f)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 // INCLUDE ---------------------------------------------------------------
32 
33 #include "scitems.hxx"
34 #include "collect.hxx"
35 #include "attrib.hxx"
36 #include "patattr.hxx"
37 #include "docpool.hxx"
38 #include "cell.hxx"
39 #include "table.hxx"
40 #include "column.hxx"
41 #include "document.hxx"
42 #include "drwlayer.hxx"
43 #include "olinetab.hxx"
44 #include "userlist.hxx"
45 #include "stlsheet.hxx"
46 #include "global.hxx"
47 #include "rechead.hxx"
48 #include "stlpool.hxx"
49 #include "stlsheet.hxx"
50 #include "brdcst.hxx"
51 #include "tabprotection.hxx"
52 #include "globstr.hrc"
53 #include "segmenttree.hxx"
54 #include <com/sun/star/sheet/TablePageBreakData.hpp>
55 
56 #include <algorithm>
57 #include <limits>
58 
59 using ::com::sun::star::uno::Sequence;
60 using ::com::sun::star::sheet::TablePageBreakData;
61 using ::std::set;
62 
63 // STATIC DATA -----------------------------------------------------------
64 
65 #define GET_SCALEVALUE(set,id) 	((const SfxUInt16Item&)(set.Get( id ))).GetValue()
66 
67 
68 void ScTable::UpdatePageBreaks( const ScRange* pUserArea )
69 {
70 	if ( pDocument->IsImportingXML() )
71 		return;
72 
73     // pUserArea != NULL -> print area is specified.  We need to force-update
74     // the page breaks.
75 
76     if (!pUserArea)
77     {
78         if (!bPageSizeValid)
79             return;
80 
81         if (mbPageBreaksValid)
82             return;
83     }
84 
85 	SfxStyleSheetBase* pStyle = pDocument->GetStyleSheetPool()->
86 									Find( aPageStyle, SFX_STYLE_FAMILY_PAGE );
87 	if ( !pStyle )
88 	{
89 		DBG_ERROR("UpdatePageBreaks: Style nicht gefunden");
90 		return;
91 	}
92 	SfxItemSet* pStyleSet = &pStyle->GetItemSet();
93 	const SfxPoolItem* pItem;
94 
95 	SCCOL nX;
96 	SCCOL nStartCol = 0;
97 	SCROW nStartRow = 0;
98 	SCCOL nEndCol = MAXCOL;
99 	SCROW nEndRow = MAXROW;
100 	if (pUserArea)
101 	{
102 		nStartCol = pUserArea->aStart.Col();
103 		nStartRow = pUserArea->aStart.Row();
104 		nEndCol = pUserArea->aEnd.Col();
105 		nEndRow = pUserArea->aEnd.Row();
106 	}
107 	else
108 	{
109 		sal_uInt16 nAreaCount = GetPrintRangeCount();
110 		if ( nAreaCount > 1 )
111 		{
112 			//	bei mehreren Bereichen nichts anzeigen:
113 
114 			for (nX=0; nX<MAXCOL; nX++)
115                 RemoveColBreak(nX, true, false);
116 
117             RemoveRowPageBreaks(0, MAXROW-1);
118 
119 			return;
120 		}
121 		else if ( nAreaCount == 1 )
122 		{
123 			const ScRange* pArea = GetPrintRange( 0 );
124 			if (pArea)
125 			{
126 				nStartCol = pArea->aStart.Col();
127 				nStartRow = pArea->aStart.Row();
128 				nEndCol = pArea->aEnd.Col();
129 				nEndRow = pArea->aEnd.Row();
130 			}
131 		}			// sonst alles
132 	}
133 
134     // get bSkipColBreaks/bSkipRowBreaks flags:
135 
136     bool bSkipColBreaks = false;
137     bool bSkipRowBreaks = false;
138 
139 	if ( pStyleSet->GetItemState( ATTR_PAGE_SCALETOPAGES, sal_False, &pItem ) == SFX_ITEM_SET )
140 	{
141 		DBG_ASSERT( pItem->ISA(SfxUInt16Item), "falsches Item" );
142         bSkipColBreaks = bSkipRowBreaks = ( ((const SfxUInt16Item*)pItem)->GetValue() > 0 );
143 	}
144 
145     if ( !bSkipColBreaks && pStyleSet->GetItemState(ATTR_PAGE_SCALETO, sal_False, &pItem) == SFX_ITEM_SET )
146     {
147         // #i54993# when fitting to width or height, ignore only manual breaks in that direction
148         const ScPageScaleToItem* pScaleToItem = static_cast<const ScPageScaleToItem*>(pItem);
149         if ( pScaleToItem->GetWidth() > 0 )
150             bSkipColBreaks = true;
151         if ( pScaleToItem->GetHeight() > 0 )
152             bSkipRowBreaks = true;
153     }
154 
155 	//--------------------------------------------------------------------------
156 
157 	long nPageSizeX = aPageSizeTwips.Width();
158 	long nPageSizeY = aPageSizeTwips.Height();
159 
160 		//	Anfang: Breaks loeschen
161 
162 	for (nX=0; nX<nStartCol; nX++)
163         RemoveColBreak(nX, true, false);
164     RemoveRowPageBreaks(0, nStartRow-1);
165 
166 	if (nStartCol > 0)
167         SetColBreak(nStartCol, true, false);  // AREABREAK
168 	if (nStartRow > 0)
169         SetRowBreak(nStartRow, true, false);  // AREABREAK
170 
171 		//	Mittelteil: Breaks verteilen
172 
173 	sal_Bool bRepeatCol = ( nRepeatStartX != SCCOL_REPEAT_NONE );
174 	sal_Bool bColFound = sal_False;
175 	long nSizeX = 0;
176 	for (nX=nStartCol; nX<=nEndCol; nX++)
177 	{
178 		sal_Bool bStartOfPage = sal_False;
179 		long nThisX = ColHidden(nX) ? 0 : pColWidth[nX];
180         bool bManualBreak = HasColManualBreak(nX);
181         if ( (nSizeX+nThisX > nPageSizeX) || (bManualBreak && !bSkipColBreaks) )
182 		{
183             SetColBreak(nX, true, false);
184 			nSizeX = 0;
185 			bStartOfPage = sal_True;
186 		}
187 		else if (nX != nStartCol)
188             RemoveColBreak(nX, true, false);
189 		else
190 			bStartOfPage = sal_True;
191 
192 		if ( bStartOfPage && bRepeatCol && nX>nRepeatStartX && !bColFound )
193 		{
194 			// subtract size of repeat columns from page size
195 			for (SCCOL i=nRepeatStartX; i<=nRepeatEndX; i++)
196 				nPageSizeX -= ColHidden(i) ? 0 : pColWidth[i];
197 			while (nX<=nRepeatEndX)
198                 RemoveColBreak(++nX, true, false);
199 			bColFound = sal_True;
200 		}
201 
202 		nSizeX += nThisX;
203 	}
204 
205     // Remove all page breaks in range.
206     RemoveRowPageBreaks(nStartRow+1, nEndRow);
207 
208     // And set new page breaks.
209 	sal_Bool bRepeatRow = ( nRepeatStartY != SCROW_REPEAT_NONE );
210 	sal_Bool bRowFound = sal_False;
211 	long nSizeY = 0;
212     ScFlatBoolRowSegments::ForwardIterator aIterHidden(*mpHiddenRows);
213     ScFlatUInt16RowSegments::ForwardIterator aIterHeights(*mpRowHeights);
214     SCROW nNextManualBreak = GetNextManualBreak(nStartRow); // -1 => no more manual breaks
215     for (SCROW nY = nStartRow; nY <= nEndRow; ++nY)
216     {
217 		sal_Bool bStartOfPage = sal_False;
218         bool bThisRowHidden = false;
219         aIterHidden.getValue(nY, bThisRowHidden);
220         long nThisY = 0;
221         if (!bThisRowHidden)
222         {
223             sal_uInt16 nTmp;
224             aIterHeights.getValue(nY, nTmp);
225             nThisY = static_cast<long>(nTmp);
226         }
227 
228         bool bManualBreak = false;
229         if (nNextManualBreak >= 0)
230         {
231             bManualBreak = (nY == nNextManualBreak);
232             if (nY >= nNextManualBreak)
233                 // Query the next menual break position.
234                 nNextManualBreak = GetNextManualBreak(nY+1);
235         }
236 
237 		if ( (nSizeY+nThisY > nPageSizeY) || (bManualBreak && !bSkipRowBreaks) )
238 		{
239             SetRowBreak(nY, true, false);
240 			nSizeY = 0;
241 			bStartOfPage = sal_True;
242 		}
243 		else if (nY != nStartRow)
244 			; // page break already removed
245 		else
246 			bStartOfPage = sal_True;
247 
248 		if ( bStartOfPage && bRepeatRow && nY>nRepeatStartY && !bRowFound )
249 		{
250 			// subtract size of repeat rows from page size
251             unsigned long nHeights = GetTotalRowHeight(nRepeatStartY, nRepeatEndY);
252 #ifdef DBG_UTIL
253             if (nHeights == ::std::numeric_limits<unsigned long>::max())
254                 DBG_ERRORFILE("ScTable::UpdatePageBreaks: row heights overflow");
255 #endif
256             nPageSizeY -= nHeights;
257             if (nY <= nRepeatEndY)
258                 RemoveRowPageBreaks(nY, nRepeatEndY);
259 			bRowFound = sal_True;
260 		}
261 
262         if (bThisRowHidden)
263         {
264             // Hidden row range.  Skip them unless there is a manual break.
265             SCROW nLastCommon = aIterHidden.getLastPos();
266             if (nNextManualBreak >= 0)
267                 nLastCommon = ::std::min(nLastCommon, nNextManualBreak-1);
268             nY = nLastCommon;
269         }
270         else
271         {
272             // Visible row range.
273 
274             SCROW nLastHidden = aIterHidden.getLastPos();
275             SCROW nLastHeight = aIterHeights.getLastPos();
276             SCROW nLastCommon = ::std::min(nLastHidden, nLastHeight);
277             if (nNextManualBreak >= 0)
278                 nLastCommon = ::std::min(nLastCommon, nNextManualBreak-1);
279 
280             if (nLastCommon > nY)
281             {
282                 long nMaxMultiple = static_cast<long>(nLastCommon - nY);
283                 long nMultiple = (nPageSizeY - nSizeY) / nThisY;
284                 if (nMultiple > nMaxMultiple)
285                     nMultiple = nMaxMultiple;
286                 if (nMultiple > 1)
287                 {
288                     nSizeY += nThisY * (nMultiple - 1);
289                     nY += nMultiple - 1;
290                 }
291             }
292         }
293 
294 		nSizeY += nThisY;
295 	}
296 
297 		//	Ende: Breaks loeschen
298 
299 	if (nEndCol < MAXCOL)
300 	{
301         SetColBreak(nEndCol+1, true, false);  // AREABREAK
302 		for (nX=nEndCol+2; nX<=MAXCOL; nX++)
303             RemoveColBreak(nX, true, false);
304 	}
305 	if (nEndRow < MAXROW)
306 	{
307         SetRowBreak(nEndRow+1, true, false);  // AREABREAK
308 		if (nEndRow+2 <= MAXROW)
309             RemoveRowPageBreaks(nEndRow+2, MAXROW);
310 	}
311     mbPageBreaksValid = !pUserArea;     // #i116881# the valid flag can only apply to the "no user area" case
312 }
313 
314 void ScTable::RemoveManualBreaks()
315 {
316     maRowManualBreaks.clear();
317     maColManualBreaks.clear();
318     InvalidatePageBreaks();
319 
320     if (IsStreamValid())
321         SetStreamValid(sal_False);
322 }
323 
324 sal_Bool ScTable::HasManualBreaks() const
325 {
326     return !maRowManualBreaks.empty() || !maColManualBreaks.empty();
327 }
328 
329 void ScTable::SetRowManualBreaks( const ::std::set<SCROW>& rBreaks )
330 {
331     maRowManualBreaks = rBreaks;
332     InvalidatePageBreaks();
333     if (IsStreamValid())
334         SetStreamValid(sal_False);
335 }
336 
337 void ScTable::SetColManualBreaks( const ::std::set<SCCOL>& rBreaks )
338 {
339     maColManualBreaks = rBreaks;
340     InvalidatePageBreaks();
341     if (IsStreamValid())
342         SetStreamValid(sal_False);
343 }
344 
345 void ScTable::GetAllRowBreaks(set<SCROW>& rBreaks, bool bPage, bool bManual) const
346 {
347     if (bPage)
348         rBreaks = maRowPageBreaks;
349 
350     if (bManual)
351     {
352         using namespace std;
353         copy(maRowManualBreaks.begin(), maRowManualBreaks.end(), inserter(rBreaks, rBreaks.begin()));
354     }
355 }
356 
357 void ScTable::GetAllColBreaks(set<SCCOL>& rBreaks, bool bPage, bool bManual) const
358 {
359     if (bPage)
360         rBreaks = maColPageBreaks;
361 
362     if (bManual)
363     {
364         using namespace std;
365         copy(maColManualBreaks.begin(), maColManualBreaks.end(), inserter(rBreaks, rBreaks.begin()));
366     }
367 }
368 
369 bool ScTable::HasRowPageBreak(SCROW nRow) const
370 {
371     if (!ValidRow(nRow))
372         return false;
373 
374     return maRowPageBreaks.find(nRow) != maRowPageBreaks.end();
375 }
376 
377 bool ScTable::HasColPageBreak(SCCOL nCol) const
378 {
379     if (!ValidCol(nCol))
380         return false;
381 
382     return maColPageBreaks.find(nCol) != maColPageBreaks.end();
383 }
384 
385 bool ScTable::HasRowManualBreak(SCROW nRow) const
386 {
387     if (!ValidRow(nRow))
388         return false;
389 
390     return maRowManualBreaks.find(nRow) != maRowManualBreaks.end();
391 }
392 
393 bool ScTable::HasColManualBreak(SCCOL nCol) const
394 {
395     if (!ValidCol(nCol))
396         return false;
397 
398     return maColManualBreaks.find(nCol) != maColManualBreaks.end();
399 }
400 
401 SCROW ScTable::GetNextManualBreak(SCROW nRow) const
402 {
403     set<SCROW>::const_iterator itr = maRowManualBreaks.lower_bound(nRow);
404     return itr == maRowManualBreaks.end() ? -1 : *itr;
405 }
406 
407 void ScTable::RemoveRowPageBreaks(SCROW nStartRow, SCROW nEndRow)
408 {
409     using namespace std;
410 
411     if (!ValidRow(nStartRow) || !ValidRow(nEndRow))
412         return;
413 
414     set<SCROW>::iterator low  = maRowPageBreaks.lower_bound(nStartRow);
415     set<SCROW>::iterator high = maRowPageBreaks.upper_bound(nEndRow);
416     maRowPageBreaks.erase(low, high);
417 }
418 
419 void ScTable::RemoveRowBreak(SCROW nRow, bool bPage, bool bManual)
420 {
421     if (!ValidRow(nRow))
422         return;
423 
424     if (bPage)
425         maRowPageBreaks.erase(nRow);
426 
427     if (bManual)
428     {
429         maRowManualBreaks.erase(nRow);
430         InvalidatePageBreaks();
431     }
432 }
433 
434 void ScTable::RemoveColBreak(SCCOL nCol, bool bPage, bool bManual)
435 {
436     if (!ValidCol(nCol))
437         return;
438 
439     if (bPage)
440         maColPageBreaks.erase(nCol);
441 
442     if (bManual)
443     {
444         maColManualBreaks.erase(nCol);
445         InvalidatePageBreaks();
446     }
447 }
448 
449 void ScTable::SetRowBreak(SCROW nRow, bool bPage, bool bManual)
450 {
451     if (!ValidRow(nRow))
452         return;
453 
454     if (bPage)
455         maRowPageBreaks.insert(nRow);
456 
457     if (bManual)
458     {
459         maRowManualBreaks.insert(nRow);
460         InvalidatePageBreaks();
461     }
462 }
463 
464 void ScTable::SetColBreak(SCCOL nCol, bool bPage, bool bManual)
465 {
466     if (!ValidCol(nCol))
467         return;
468 
469     if (bPage)
470         maColPageBreaks.insert(nCol);
471 
472     if (bManual)
473     {
474         maColManualBreaks.insert(nCol);
475         InvalidatePageBreaks();
476     }
477 }
478 
479 Sequence<TablePageBreakData> ScTable::GetRowBreakData() const
480 {
481     using ::std::copy;
482     using ::std::inserter;
483 
484     set<SCROW> aRowBreaks = maRowPageBreaks;
485     copy(maRowManualBreaks.begin(), maRowManualBreaks.end(), inserter(aRowBreaks, aRowBreaks.begin()));
486 
487     set<SCROW>::const_iterator itr = aRowBreaks.begin(), itrEnd = aRowBreaks.end();
488     Sequence<TablePageBreakData> aSeq(aRowBreaks.size());
489 
490     for (sal_Int32 i = 0; itr != itrEnd; ++itr, ++i)
491     {
492         SCROW nRow = *itr;
493         TablePageBreakData aData;
494         aData.Position = nRow;
495         aData.ManualBreak = HasRowManualBreak(nRow);
496         aSeq[i] = aData;
497     }
498 
499     return aSeq;
500 }
501 
502 bool ScTable::RowHidden(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
503 {
504     if (!ValidRow(nRow))
505     {
506         if (pFirstRow)
507             *pFirstRow = nRow;
508         if (pLastRow)
509             *pLastRow = nRow;
510         return true;
511     }
512 
513     ScFlatBoolRowSegments::RangeData aData;
514     if (!mpHiddenRows->getRangeData(nRow, aData))
515     {
516         // search failed.
517         if (pFirstRow)
518             *pFirstRow = nRow;
519         if (pLastRow)
520             *pLastRow = nRow;
521         return true;
522     }
523 
524     if (pFirstRow)
525         *pFirstRow = aData.mnRow1;
526     if (pLastRow)
527         *pLastRow = aData.mnRow2;
528 
529     return aData.mbValue;
530 }
531 
532 
533 bool ScTable::RowHidden(SCROW nRow, SCROW& rLastRow) const
534 {
535     rLastRow = nRow;
536     if (!ValidRow(nRow))
537         return true;
538 
539     ScFlatBoolRowSegments::RangeData aData;
540     if (!mpHiddenRows->getRangeData(nRow, aData))
541         // search failed.
542         return true;
543 
544     rLastRow = aData.mnRow2;
545     return aData.mbValue;
546 }
547 
548 bool ScTable::HasHiddenRows(SCROW nStartRow, SCROW nEndRow) const
549 {
550     SCROW nRow = nStartRow;
551     while (nRow <= nEndRow)
552     {
553         SCROW nLastRow = -1;
554         bool bHidden = RowHidden(nRow, nLastRow);
555         if (bHidden)
556             return true;
557 
558         nRow = nLastRow + 1;
559     }
560     return false;
561 }
562 
563 bool ScTable::ColHidden(SCCOL nCol, SCCOL& rLastCol) const
564 {
565     rLastCol = nCol;
566     if (!ValidCol(nCol))
567         return true;
568 
569     ScFlatBoolColSegments::RangeData aData;
570     if (!mpHiddenCols->getRangeData(nCol, aData))
571         return true;
572 
573     rLastCol = aData.mnCol2;
574     return aData.mbValue;
575 }
576 
577 bool ScTable::ColHidden(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const
578 {
579     if (!ValidCol(nCol))
580         return true;
581 
582     ScFlatBoolColSegments::RangeData aData;
583     if (!mpHiddenCols->getRangeData(nCol, aData))
584         return true;
585 
586     if (pFirstCol)
587         *pFirstCol = aData.mnCol1;
588     if (pLastCol)
589         *pLastCol = aData.mnCol2;
590 
591     return aData.mbValue;
592 }
593 
594 void ScTable::SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden)
595 {
596     if (bHidden)
597         mpHiddenRows->setTrue(nStartRow, nEndRow);
598     else
599         mpHiddenRows->setFalse(nStartRow, nEndRow);
600 }
601 
602 void ScTable::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, bool bHidden)
603 {
604     if (bHidden)
605         mpHiddenCols->setTrue(nStartCol, nEndCol);
606     else
607         mpHiddenCols->setFalse(nStartCol, nEndCol);
608 }
609 
610 void ScTable::CopyColHidden(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol)
611 {
612     SCCOL nCol = nStartCol;
613     while (nCol <= nEndCol)
614     {
615         SCCOL nLastCol;
616         bool bHidden = rTable.ColHidden(nCol, NULL, &nLastCol);
617         if (nLastCol > nEndCol)
618             nLastCol = nEndCol;
619 
620         SetColHidden(nCol, nLastCol, bHidden);
621         nCol = nLastCol + 1;
622     }
623 }
624 
625 void ScTable::CopyRowHidden(ScTable& rTable, SCROW nStartRow, SCROW nEndRow)
626 {
627     SCROW nRow = nStartRow;
628     while (nRow <= nEndRow)
629     {
630         SCROW nLastRow = -1;
631         bool bHidden = rTable.RowHidden(nRow, nLastRow);
632         if (nLastRow > nEndRow)
633             nLastRow = nEndRow;
634         SetRowHidden(nRow, nLastRow, bHidden);
635         nRow = nLastRow + 1;
636     }
637 }
638 
639 void ScTable::CopyRowHeight(ScTable& rSrcTable, SCROW nStartRow, SCROW nEndRow, SCROW nSrcOffset)
640 {
641     SCROW nRow = nStartRow;
642     ScFlatUInt16RowSegments::RangeData aSrcData;
643     while (nRow <= nEndRow)
644     {
645         if (!rSrcTable.mpRowHeights->getRangeData(nRow + nSrcOffset, aSrcData))
646             // Something is wrong !
647             return;
648 
649         SCROW nLastRow = aSrcData.mnRow2 - nSrcOffset;
650         if (nLastRow > nEndRow)
651             nLastRow = nEndRow;
652 
653         mpRowHeights->setValue(nRow, nLastRow, aSrcData.mnValue);
654         nRow = nLastRow + 1;
655     }
656 }
657 
658 SCROW ScTable::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow) const
659 {
660     SCROW nRow = nStartRow;
661     ScFlatBoolRowSegments::RangeData aData;
662     while (nRow <= nEndRow)
663     {
664         if (!ValidRow(nRow))
665             break;
666 
667         if (!mpHiddenRows->getRangeData(nRow, aData))
668             // failed to get range data.
669             break;
670 
671         if (!aData.mbValue)
672             // visible row found
673             return nRow;
674 
675         nRow = aData.mnRow2 + 1;
676     }
677 
678     return ::std::numeric_limits<SCROW>::max();
679 }
680 
681 SCROW ScTable::LastVisibleRow(SCROW nStartRow, SCROW nEndRow) const
682 {
683     SCROW nRow = nEndRow;
684     ScFlatBoolRowSegments::RangeData aData;
685     while (nRow >= nStartRow)
686     {
687         if (!ValidRow(nRow))
688             break;
689 
690         if (!mpHiddenRows->getRangeData(nRow, aData))
691             // failed to get range data.
692             break;
693 
694         if (!aData.mbValue)
695             // visible row found
696             return nRow;
697 
698         nRow = aData.mnRow1 - 1;
699     }
700 
701     return ::std::numeric_limits<SCROW>::max();
702 }
703 
704 SCROW ScTable::CountVisibleRows(SCROW nStartRow, SCROW nEndRow) const
705 {
706     SCROW nCount = 0;
707     SCROW nRow = nStartRow;
708     ScFlatBoolRowSegments::RangeData aData;
709     while (nRow <= nEndRow)
710     {
711         if (!mpHiddenRows->getRangeData(nRow, aData))
712             break;
713 
714         if (aData.mnRow2 > nEndRow)
715             aData.mnRow2 = nEndRow;
716 
717         if (!aData.mbValue)
718             nCount += aData.mnRow2 - nRow + 1;
719 
720         nRow = aData.mnRow2 + 1;
721     }
722     return nCount;
723 }
724 
725 sal_uInt32 ScTable::GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow) const
726 {
727     sal_uInt32 nHeight = 0;
728     SCROW nRow = nStartRow;
729     ScFlatBoolRowSegments::RangeData aData;
730     while (nRow <= nEndRow)
731     {
732         if (!mpHiddenRows->getRangeData(nRow, aData))
733             break;
734 
735         if (aData.mnRow2 > nEndRow)
736             aData.mnRow2 = nEndRow;
737 
738         if (!aData.mbValue)
739             // visible row range.
740             nHeight += mpRowHeights->getSumValue(nRow, aData.mnRow2);
741 
742         nRow = aData.mnRow2 + 1;
743     }
744 
745     return nHeight;
746 }
747 
748 SCCOLROW ScTable::LastHiddenColRow(SCCOLROW nPos, bool bCol) const
749 {
750     if (bCol)
751     {
752         SCCOL nCol = static_cast<SCCOL>(nPos);
753         if (ColHidden(nCol))
754         {
755             for (SCCOL i = nCol+1; i <= MAXCOL; ++i)
756             {
757                 if (!ColHidden(nCol))
758                     return nCol - 1;
759             }
760         }
761     }
762     else
763     {
764         SCROW nRow = static_cast<SCROW>(nPos);
765         SCROW nLastRow;
766         if (RowHidden(nRow, NULL, &nLastRow))
767             return static_cast<SCCOLROW>(nLastRow);
768     }
769     return ::std::numeric_limits<SCCOLROW>::max();
770 }
771 
772 bool ScTable::RowFiltered(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
773 {
774     if (!ValidRow(nRow))
775         return false;
776 
777     ScFlatBoolRowSegments::RangeData aData;
778     if (!mpFilteredRows->getRangeData(nRow, aData))
779         // search failed.
780         return false;
781 
782     if (pFirstRow)
783         *pFirstRow = aData.mnRow1;
784     if (pLastRow)
785         *pLastRow = aData.mnRow2;
786 
787     return aData.mbValue;
788 }
789 
790 bool ScTable::ColFiltered(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const
791 {
792     if (!ValidCol(nCol))
793         return false;
794 
795     ScFlatBoolColSegments::RangeData aData;
796     if (!mpFilteredCols->getRangeData(nCol, aData))
797         // search failed.
798         return false;
799 
800     if (pFirstCol)
801         *pFirstCol = aData.mnCol1;
802     if (pLastCol)
803         *pLastCol = aData.mnCol2;
804 
805     return aData.mbValue;
806 }
807 
808 bool ScTable::HasFilteredRows(SCROW nStartRow, SCROW nEndRow) const
809 {
810     SCROW nRow = nStartRow;
811     while (nRow <= nEndRow)
812     {
813         SCROW nLastRow = nRow;
814         bool bFiltered = RowFiltered(nRow, NULL, &nLastRow);
815         if (bFiltered)
816             return true;
817 
818         nRow = nLastRow + 1;
819     }
820     return false;
821 }
822 
823 void ScTable::CopyColFiltered(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol)
824 {
825     SCCOL nCol = nStartCol;
826     while (nCol <= nEndCol)
827     {
828         SCCOL nLastCol;
829         bool bFiltered = rTable.ColFiltered(nCol, NULL, &nLastCol);
830         if (nLastCol > nEndCol)
831             nLastCol = nEndCol;
832 
833         SetColFiltered(nCol, nLastCol, bFiltered);
834         nCol = nLastCol + 1;
835     }
836 }
837 
838 void ScTable::CopyRowFiltered(ScTable& rTable, SCROW nStartRow, SCROW nEndRow)
839 {
840     SCROW nRow = nStartRow;
841     while (nRow <= nEndRow)
842     {
843         SCROW nLastRow = -1;
844         bool bFiltered = rTable.RowFiltered(nRow, NULL, &nLastRow);
845         if (nLastRow > nEndRow)
846             nLastRow = nEndRow;
847         SetRowFiltered(nRow, nLastRow, bFiltered);
848         nRow = nLastRow + 1;
849     }
850 }
851 
852 void ScTable::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, bool bFiltered)
853 {
854     if (bFiltered)
855         mpFilteredRows->setTrue(nStartRow, nEndRow);
856     else
857         mpFilteredRows->setFalse(nStartRow, nEndRow);
858 }
859 
860 void ScTable::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, bool bFiltered)
861 {
862     if (bFiltered)
863         mpFilteredCols->setTrue(nStartCol, nEndCol);
864     else
865         mpFilteredCols->setFalse(nStartCol, nEndCol);
866 }
867 
868 SCROW ScTable::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const
869 {
870     SCROW nRow = nStartRow;
871     ScFlatBoolRowSegments::RangeData aData;
872     while (nRow <= nEndRow)
873     {
874         if (!ValidRow(nRow))
875             break;
876 
877         if (!mpFilteredRows->getRangeData(nRow, aData))
878             // failed to get range data.
879             break;
880 
881         if (!aData.mbValue)
882             // non-filtered row found
883             return nRow;
884 
885         nRow = aData.mnRow2 + 1;
886     }
887 
888     return ::std::numeric_limits<SCROW>::max();
889 }
890 
891 SCROW ScTable::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const
892 {
893     SCROW nRow = nEndRow;
894     ScFlatBoolRowSegments::RangeData aData;
895     while (nRow >= nStartRow)
896     {
897         if (!ValidRow(nRow))
898             break;
899 
900         if (!mpFilteredRows->getRangeData(nRow, aData))
901             // failed to get range data.
902             break;
903 
904         if (!aData.mbValue)
905             // non-filtered row found
906             return nRow;
907 
908         nRow = aData.mnRow1 - 1;
909     }
910 
911     return ::std::numeric_limits<SCROW>::max();
912 }
913 
914 SCROW ScTable::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow) const
915 {
916     SCROW nCount = 0;
917     SCROW nRow = nStartRow;
918     ScFlatBoolRowSegments::RangeData aData;
919     while (nRow <= nEndRow)
920     {
921         if (!mpFilteredRows->getRangeData(nRow, aData))
922             break;
923 
924         if (aData.mnRow2 > nEndRow)
925             aData.mnRow2 = nEndRow;
926 
927         if (!aData.mbValue)
928             nCount += aData.mnRow2 - nRow + 1;
929 
930         nRow = aData.mnRow2 + 1;
931     }
932     return nCount;
933 }
934 
935 namespace {
936 
937 void lcl_syncFlags(ScFlatBoolColSegments& rColSegments, ScFlatBoolRowSegments& rRowSegments,
938     sal_uInt8* pColFlags, ScBitMaskCompressedArray< SCROW, sal_uInt8>* pRowFlags, const sal_uInt8 nFlagMask)
939 {
940     using ::sal::static_int_cast;
941 
942     pRowFlags->AndValue(0, MAXROW, static_int_cast<sal_uInt8>(~nFlagMask));
943     for (SCCOL i = 0; i <= MAXCOL; ++i)
944         pColFlags[i] &= static_int_cast<sal_uInt8>(~nFlagMask);
945 
946     {
947         // row hidden flags.
948 
949         SCROW nRow = 0;
950         ScFlatBoolRowSegments::RangeData aData;
951         while (nRow <= MAXROW)
952         {
953             if (!rRowSegments.getRangeData(nRow, aData))
954                 break;
955 
956             if (aData.mbValue)
957                 pRowFlags->OrValue(nRow, aData.mnRow2, static_int_cast<sal_uInt8>(nFlagMask));
958 
959             nRow = aData.mnRow2 + 1;
960         }
961     }
962 
963     {
964         // column hidden flags.
965 
966         SCCOL nCol = 0;
967         ScFlatBoolColSegments::RangeData aData;
968         while (nCol <= MAXCOL)
969         {
970             if (!rColSegments.getRangeData(nCol, aData))
971                 break;
972 
973             if (aData.mbValue)
974             {
975                 for (SCCOL i = nCol; i <= aData.mnCol2; ++i)
976                     pColFlags[i] |= nFlagMask;
977             }
978 
979             nCol = aData.mnCol2 + 1;
980         }
981     }
982 }
983 
984 }
985 
986 void ScTable::SyncColRowFlags()
987 {
988     using ::sal::static_int_cast;
989 
990     // Manual breaks.
991     pRowFlags->AndValue(0, MAXROW, static_int_cast<sal_uInt8>(~CR_MANUALBREAK));
992     for (SCCOL i = 0; i <= MAXCOL; ++i)
993         pColFlags[i] &= static_int_cast<sal_uInt8>(~CR_MANUALBREAK);
994 
995     if (!maRowManualBreaks.empty())
996     {
997         for (set<SCROW>::const_iterator itr = maRowManualBreaks.begin(), itrEnd = maRowManualBreaks.end();
998               itr != itrEnd; ++itr)
999             pRowFlags->OrValue(*itr, static_int_cast<sal_uInt8>(CR_MANUALBREAK));
1000     }
1001 
1002     if (!maColManualBreaks.empty())
1003     {
1004         for (set<SCCOL>::const_iterator itr = maColManualBreaks.begin(), itrEnd = maColManualBreaks.end();
1005               itr != itrEnd; ++itr)
1006             pColFlags[*itr] |= CR_MANUALBREAK;
1007     }
1008 
1009     // Hidden flags.
1010     lcl_syncFlags(*mpHiddenCols, *mpHiddenRows, pColFlags, pRowFlags, CR_HIDDEN);
1011     lcl_syncFlags(*mpFilteredCols, *mpFilteredRows, pColFlags, pRowFlags, CR_FILTERED);
1012 }
1013 
1014 void ScTable::SetPageSize( const Size& rSize )
1015 {
1016 	if ( rSize.Width() != 0 && rSize.Height() != 0 )
1017 	{
1018         if (aPageSizeTwips != rSize)
1019             InvalidatePageBreaks();
1020 
1021 		bPageSizeValid = sal_True;
1022 		aPageSizeTwips = rSize;
1023 	}
1024 	else
1025 		bPageSizeValid = sal_False;
1026 }
1027 
1028 sal_Bool ScTable::IsProtected() const
1029 {
1030     return pTabProtection.get() && pTabProtection->isProtected();
1031 }
1032 
1033 void ScTable::SetProtection(const ScTableProtection* pProtect)
1034 {
1035     if (pProtect)
1036         pTabProtection.reset(new ScTableProtection(*pProtect));
1037     else
1038         pTabProtection.reset(NULL);
1039 
1040     if (IsStreamValid())
1041         SetStreamValid(sal_False);
1042 }
1043 
1044 ScTableProtection* ScTable::GetProtection()
1045 {
1046     return pTabProtection.get();
1047 }
1048 
1049 Size ScTable::GetPageSize() const
1050 {
1051 	if ( bPageSizeValid )
1052 		return aPageSizeTwips;
1053 	else
1054 		return Size();	// leer
1055 }
1056 
1057 void ScTable::SetRepeatArea( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
1058 {
1059     // #i117952# page break calculation uses these values (set from ScPrintFunc), not pRepeatColRange/pRepeatRowRange
1060     if ( nStartCol != nRepeatStartX || nEndCol != nRepeatEndX || nStartRow != nRepeatStartY || nEndRow != nRepeatEndY )
1061         InvalidatePageBreaks();
1062 
1063 	nRepeatStartX = nStartCol;
1064 	nRepeatEndX   = nEndCol;
1065 	nRepeatStartY = nStartRow;
1066 	nRepeatEndY   = nEndRow;
1067 }
1068 
1069 void ScTable::StartListening( const ScAddress& rAddress, SvtListener* pListener )
1070 {
1071 	aCol[rAddress.Col()].StartListening( *pListener, rAddress.Row() );
1072 }
1073 
1074 void ScTable::EndListening( const ScAddress& rAddress, SvtListener* pListener )
1075 {
1076 	aCol[rAddress.Col()].EndListening( *pListener, rAddress.Row() );
1077 }
1078 
1079 void ScTable::SetPageStyle( const String& rName )
1080 {
1081 	if ( aPageStyle != rName )
1082 	{
1083 		String					aStrNew    = rName;
1084 		SfxStyleSheetBasePool*	pStylePool = pDocument->GetStyleSheetPool();
1085 		SfxStyleSheetBase*		pNewStyle  = pStylePool->Find( aStrNew, SFX_STYLE_FAMILY_PAGE );
1086 
1087 		if ( !pNewStyle )
1088 		{
1089 			aStrNew = ScGlobal::GetRscString(STR_STYLENAME_STANDARD);
1090 			pNewStyle = pStylePool->Find( aStrNew, SFX_STYLE_FAMILY_PAGE );
1091 		}
1092 
1093 		if ( aPageStyle != aStrNew )
1094 		{
1095 			SfxStyleSheetBase* pOldStyle = pStylePool->Find( aPageStyle, SFX_STYLE_FAMILY_PAGE );
1096 
1097 			if ( pOldStyle && pNewStyle )
1098 			{
1099 				SfxItemSet&  rOldSet		  = pOldStyle->GetItemSet();
1100 				SfxItemSet&  rNewSet 		  = pNewStyle->GetItemSet();
1101 				const sal_uInt16 nOldScale		  = GET_SCALEVALUE(rOldSet,ATTR_PAGE_SCALE);
1102 				const sal_uInt16 nOldScaleToPages = GET_SCALEVALUE(rOldSet,ATTR_PAGE_SCALETOPAGES);
1103 				const sal_uInt16 nNewScale		  = GET_SCALEVALUE(rNewSet,ATTR_PAGE_SCALE);
1104 				const sal_uInt16 nNewScaleToPages = GET_SCALEVALUE(rNewSet,ATTR_PAGE_SCALETOPAGES);
1105 
1106 				if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
1107                     InvalidateTextWidth(NULL, NULL, sal_False, sal_False);
1108 			}
1109 
1110 			if ( pNewStyle )			// auch ohne den alten (fuer UpdateStdNames)
1111 				aPageStyle = aStrNew;
1112 
1113             if (IsStreamValid())
1114                 SetStreamValid(sal_False);
1115 		}
1116 	}
1117 }
1118 
1119 void ScTable::PageStyleModified( const String& rNewName )
1120 {
1121 	aPageStyle = rNewName;
1122     InvalidateTextWidth(NULL, NULL, sal_False, sal_False);      // don't know what was in the style before
1123 }
1124 
1125 void ScTable::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
1126                                    sal_Bool bNumFormatChanged, sal_Bool bBroadcast )
1127 {
1128 	if ( pAdrFrom && !pAdrTo )
1129 	{
1130 		ScBaseCell* pCell = aCol[pAdrFrom->Col()].GetCell( pAdrFrom->Row() );
1131 		if ( pCell )
1132 		{
1133 			pCell->SetTextWidth( TEXTWIDTH_DIRTY );
1134             if ( bNumFormatChanged )
1135                 pCell->SetScriptType( SC_SCRIPTTYPE_UNKNOWN );
1136 			if ( bBroadcast )
1137 			{	// nur bei CalcAsShown
1138 				switch ( pCell->GetCellType() )
1139 				{
1140 					case CELLTYPE_VALUE :
1141 						pDocument->Broadcast( SC_HINT_DATACHANGED,
1142 							ScAddress( pAdrFrom->Col(), pAdrFrom->Row(), nTab ),
1143 							pCell );
1144 						break;
1145 					case CELLTYPE_FORMULA :
1146 						((ScFormulaCell*)pCell)->SetDirty();
1147 						break;
1148                     default:
1149                     {
1150                         // added to avoid warnings
1151                     }
1152 				}
1153 			}
1154 		}
1155 	}
1156 	else
1157 	{
1158 		const SCCOL nColStart = pAdrFrom ? pAdrFrom->Col() : 0;
1159 		const SCROW nRowStart = pAdrFrom ? pAdrFrom->Row() : 0;
1160 		const SCCOL nColEnd   = pAdrTo   ? pAdrTo->Col()   : MAXCOL;
1161 		const SCROW nRowEnd   = pAdrTo   ? pAdrTo->Row()   : MAXROW;
1162 
1163 		for ( SCCOL nCol=nColStart; nCol<=nColEnd; nCol++ )
1164 		{
1165 			ScColumnIterator aIter( &aCol[nCol], nRowStart, nRowEnd );
1166 			ScBaseCell*		 pCell = NULL;
1167 			SCROW			 nRow  = nRowStart;
1168 
1169 			while ( aIter.Next( nRow, pCell ) )
1170 			{
1171 				pCell->SetTextWidth( TEXTWIDTH_DIRTY );
1172                 if ( bNumFormatChanged )
1173                     pCell->SetScriptType( SC_SCRIPTTYPE_UNKNOWN );
1174 				if ( bBroadcast )
1175 				{	// nur bei CalcAsShown
1176 					switch ( pCell->GetCellType() )
1177 					{
1178 						case CELLTYPE_VALUE :
1179 							pDocument->Broadcast( SC_HINT_DATACHANGED,
1180 								ScAddress( nCol, nRow, nTab ), pCell );
1181 							break;
1182 						case CELLTYPE_FORMULA :
1183 							((ScFormulaCell*)pCell)->SetDirty();
1184 							break;
1185                         default:
1186                         {
1187                             // added to avoid warnings
1188                         }
1189 					}
1190 				}
1191 			}
1192 		}
1193 	}
1194 }
1195 
1196 
1197 
1198 
1199 
1200