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