fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / data / table5.cxx
blob5924d3ec43057aba8019313c9231be0edc9d0ad5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include "attrib.hxx"
22 #include "patattr.hxx"
23 #include "docpool.hxx"
24 #include "formulacell.hxx"
25 #include "table.hxx"
26 #include "column.hxx"
27 #include "document.hxx"
28 #include "drwlayer.hxx"
29 #include "olinetab.hxx"
30 #include "userlist.hxx"
31 #include "stlsheet.hxx"
32 #include "global.hxx"
33 #include "rechead.hxx"
34 #include "stlpool.hxx"
35 #include "brdcst.hxx"
36 #include "tabprotection.hxx"
37 #include "globstr.hrc"
38 #include "segmenttree.hxx"
39 #include "columniterator.hxx"
40 #include "globalnames.hxx"
41 #include "scmod.hxx"
42 #include "printopt.hxx"
44 #include <com/sun/star/sheet/TablePageBreakData.hpp>
46 #include <algorithm>
47 #include <limits>
48 #include <iostream>
50 using ::com::sun::star::uno::Sequence;
51 using ::com::sun::star::sheet::TablePageBreakData;
52 using ::std::set;
54 // STATIC DATA -----------------------------------------------------------
56 #define GET_SCALEVALUE(set,id) static_cast<const SfxUInt16Item&>(set.Get( id )).GetValue()
58 void ScTable::UpdatePageBreaks( const ScRange* pUserArea )
60 if ( pDocument->IsImportingXML() )
61 return;
63 // pUserArea != NULL -> print area is specified. We need to force-update
64 // the page breaks.
66 if (!pUserArea)
68 if (!bPageSizeValid)
69 return;
71 // Always update breaks if force breaks option has changed
72 if (mbPageBreaksValid && mbForceBreaks == SC_MOD()->GetPrintOptions().GetForceBreaks())
73 return;
76 SfxStyleSheetBase* pStyle = pDocument->GetStyleSheetPool()->
77 Find( aPageStyle, SFX_STYLE_FAMILY_PAGE );
78 if ( !pStyle )
80 OSL_FAIL("UpdatePageBreaks: Style not found");
81 return;
83 SfxItemSet* pStyleSet = &pStyle->GetItemSet();
84 const SfxPoolItem* pItem;
86 SCCOL nX;
87 SCCOL nStartCol = 0;
88 SCROW nStartRow = 0;
89 SCCOL nEndCol = MAXCOL;
90 SCROW nEndRow = MAXROW;
91 if (pUserArea)
93 nStartCol = pUserArea->aStart.Col();
94 nStartRow = pUserArea->aStart.Row();
95 nEndCol = pUserArea->aEnd.Col();
96 nEndRow = pUserArea->aEnd.Row();
98 else
100 sal_uInt16 nAreaCount = GetPrintRangeCount();
101 if ( nAreaCount > 1 )
103 // Show nothing, when multiple ranges
105 for (nX=0; nX<MAXCOL; nX++)
106 RemoveColBreak(nX, true, false);
108 RemoveRowPageBreaks(0, MAXROW-1);
110 return;
112 else if ( nAreaCount == 1 )
114 const ScRange* pArea = GetPrintRange( 0 );
115 if (pArea)
117 nStartCol = pArea->aStart.Col();
118 nStartRow = pArea->aStart.Row();
119 nEndCol = pArea->aEnd.Col();
120 nEndRow = pArea->aEnd.Row();
122 } // otherwise show everything
125 // get bSkipColBreaks/bSkipRowBreaks flags:
126 // fdo#40788 - print range scale settings can cause manual breaks to be
127 // ignored (see below). This behaviour may now be set by the user.
128 mbForceBreaks = SC_MOD()->GetPrintOptions().GetForceBreaks();
129 bool bSkipColBreaks = false;
130 bool bSkipRowBreaks = false;
132 if (!mbForceBreaks)
134 if ( pStyleSet->GetItemState( ATTR_PAGE_SCALETOPAGES, false, &pItem ) == SfxItemState::SET )
136 OSL_ENSURE( pItem->ISA(SfxUInt16Item), "invalid Item" );
137 bSkipColBreaks = bSkipRowBreaks = static_cast<const SfxUInt16Item*>(pItem)->GetValue() > 0;
140 if ( !bSkipColBreaks && pStyleSet->GetItemState(ATTR_PAGE_SCALETO, false, &pItem) == SfxItemState::SET )
142 // #i54993# when fitting to width or height, ignore only manual breaks in that direction
143 const ScPageScaleToItem* pScaleToItem = static_cast<const ScPageScaleToItem*>(pItem);
144 if ( pScaleToItem->GetWidth() > 0 )
145 bSkipColBreaks = true;
146 if ( pScaleToItem->GetHeight() > 0 )
147 bSkipRowBreaks = true;
151 long nPageSizeX = aPageSizeTwips.Width();
152 long nPageSizeY = aPageSizeTwips.Height();
154 // Beginning: Remove breaks
156 for (nX=0; nX<nStartCol; nX++)
157 RemoveColBreak(nX, true, false);
158 RemoveRowPageBreaks(0, nStartRow-1);
160 if (nStartCol > 0)
161 SetColBreak(nStartCol, true, false); // AREABREAK
162 if (nStartRow > 0)
163 SetRowBreak(nStartRow, true, false); // AREABREAK
165 // Middle part: Distribute breaks
167 bool bRepeatCol = ( nRepeatStartX != SCCOL_REPEAT_NONE );
168 bool bColFound = false;
169 long nSizeX = 0;
170 for (nX=nStartCol; nX<=nEndCol; nX++)
172 bool bStartOfPage = false;
173 long nThisX = ColHidden(nX) ? 0 : pColWidth[nX];
174 bool bManualBreak = HasColManualBreak(nX);
175 if ( (nSizeX+nThisX > nPageSizeX) || (bManualBreak && !bSkipColBreaks) )
177 SetColBreak(nX, true, false);
178 nSizeX = 0;
179 bStartOfPage = true;
181 else if (nX != nStartCol)
182 RemoveColBreak(nX, true, false);
183 else
184 bStartOfPage = true;
186 if ( bStartOfPage && bRepeatCol && nX>nRepeatStartX && !bColFound )
188 // subtract size of repeat columns from page size
189 for (SCCOL i=nRepeatStartX; i<=nRepeatEndX; i++)
190 nPageSizeX -= ColHidden(i) ? 0 : pColWidth[i];
191 while (nX<=nRepeatEndX)
192 RemoveColBreak(++nX, true, false);
193 bColFound = true;
196 nSizeX += nThisX;
199 // Remove all page breaks in range.
200 RemoveRowPageBreaks(nStartRow+1, nEndRow);
202 // And set new page breaks.
203 bool bRepeatRow = ( nRepeatStartY != SCROW_REPEAT_NONE );
204 bool bRowFound = false;
205 long nSizeY = 0;
206 ScFlatBoolRowSegments::ForwardIterator aIterHidden(*mpHiddenRows);
207 ScFlatUInt16RowSegments::ForwardIterator aIterHeights(*mpRowHeights);
208 SCROW nNextManualBreak = GetNextManualBreak(nStartRow); // -1 => no more manual breaks
209 for (SCROW nY = nStartRow; nY <= nEndRow; ++nY)
211 bool bStartOfPage = false;
212 bool bThisRowHidden = false;
213 aIterHidden.getValue(nY, bThisRowHidden);
214 long nThisY = 0;
215 if (!bThisRowHidden)
217 sal_uInt16 nTmp;
218 aIterHeights.getValue(nY, nTmp);
219 nThisY = static_cast<long>(nTmp);
222 bool bManualBreak = false;
223 if (nNextManualBreak >= 0)
225 bManualBreak = (nY == nNextManualBreak);
226 if (nY >= nNextManualBreak)
227 // Query the next menual break position.
228 nNextManualBreak = GetNextManualBreak(nY+1);
231 if ( (nSizeY+nThisY > nPageSizeY) || (bManualBreak && !bSkipRowBreaks) )
233 SetRowBreak(nY, true, false);
234 nSizeY = 0;
235 bStartOfPage = true;
237 else if (nY != nStartRow)
238 ; // page break already removed
239 else
240 bStartOfPage = true;
242 if ( bStartOfPage && bRepeatRow && nY>nRepeatStartY && !bRowFound )
244 // subtract size of repeat rows from page size
245 unsigned long nHeights = GetTotalRowHeight(nRepeatStartY, nRepeatEndY);
246 #if OSL_DEBUG_LEVEL > 0
247 if (nHeights == ::std::numeric_limits<unsigned long>::max())
248 OSL_FAIL("ScTable::UpdatePageBreaks: row heights overflow");
249 #endif
250 nPageSizeY -= nHeights;
251 if (nY <= nRepeatEndY)
252 RemoveRowPageBreaks(nY, nRepeatEndY);
253 bRowFound = true;
256 if (bThisRowHidden)
258 // Hidden row range. Skip them unless there is a manual break.
259 SCROW nLastCommon = aIterHidden.getLastPos();
260 if (nNextManualBreak >= 0)
261 nLastCommon = ::std::min(nLastCommon, nNextManualBreak-1);
262 nY = nLastCommon;
264 else
266 // Visible row range.
268 SCROW nLastHidden = aIterHidden.getLastPos();
269 SCROW nLastHeight = aIterHeights.getLastPos();
270 SCROW nLastCommon = ::std::min(nLastHidden, nLastHeight);
271 if (nNextManualBreak >= 0)
272 nLastCommon = ::std::min(nLastCommon, nNextManualBreak-1);
274 if (nLastCommon > nY)
276 long nMaxMultiple = static_cast<long>(nLastCommon - nY);
277 long nMultiple = (nPageSizeY - nSizeY) / nThisY;
278 if (nMultiple > nMaxMultiple)
279 nMultiple = nMaxMultiple;
280 if (nMultiple > 1)
282 nSizeY += nThisY * (nMultiple - 1);
283 nY += nMultiple - 1;
288 nSizeY += nThisY;
291 // End: Remove Break
293 if (nEndCol < MAXCOL)
295 SetColBreak(nEndCol+1, true, false); // AREABREAK
296 for (nX=nEndCol+2; nX<=MAXCOL; nX++)
297 RemoveColBreak(nX, true, false);
299 if (nEndRow < MAXROW)
301 SetRowBreak(nEndRow+1, true, false); // AREABREAK
302 if (nEndRow+2 <= MAXROW)
303 RemoveRowPageBreaks(nEndRow+2, MAXROW);
305 mbPageBreaksValid = !pUserArea; // #i116881# the valid flag can only apply to the "no user area" case
308 void ScTable::RemoveManualBreaks()
310 maRowManualBreaks.clear();
311 maColManualBreaks.clear();
312 InvalidatePageBreaks();
314 if (IsStreamValid())
315 SetStreamValid(false);
318 bool ScTable::HasManualBreaks() const
320 return !maRowManualBreaks.empty() || !maColManualBreaks.empty();
323 void ScTable::SetRowManualBreaks( const ::std::set<SCROW>& rBreaks )
325 maRowManualBreaks = rBreaks;
326 InvalidatePageBreaks();
327 if (IsStreamValid())
328 SetStreamValid(false);
331 void ScTable::SetColManualBreaks( const ::std::set<SCCOL>& rBreaks )
333 maColManualBreaks = rBreaks;
334 InvalidatePageBreaks();
335 if (IsStreamValid())
336 SetStreamValid(false);
339 void ScTable::GetAllRowBreaks(set<SCROW>& rBreaks, bool bPage, bool bManual) const
341 if (bPage)
342 rBreaks = maRowPageBreaks;
344 if (bManual)
346 using namespace std;
347 copy(maRowManualBreaks.begin(), maRowManualBreaks.end(), inserter(rBreaks, rBreaks.begin()));
351 void ScTable::GetAllColBreaks(set<SCCOL>& rBreaks, bool bPage, bool bManual) const
353 if (bPage)
354 rBreaks = maColPageBreaks;
356 if (bManual)
358 using namespace std;
359 copy(maColManualBreaks.begin(), maColManualBreaks.end(), inserter(rBreaks, rBreaks.begin()));
363 bool ScTable::HasRowPageBreak(SCROW nRow) const
365 if (!ValidRow(nRow))
366 return false;
368 return maRowPageBreaks.find(nRow) != maRowPageBreaks.end();
371 bool ScTable::HasColPageBreak(SCCOL nCol) const
373 if (!ValidCol(nCol))
374 return false;
376 return maColPageBreaks.find(nCol) != maColPageBreaks.end();
379 bool ScTable::HasRowManualBreak(SCROW nRow) const
381 if (!ValidRow(nRow))
382 return false;
384 return maRowManualBreaks.find(nRow) != maRowManualBreaks.end();
387 bool ScTable::HasColManualBreak(SCCOL nCol) const
389 if (!ValidCol(nCol))
390 return false;
392 return maColManualBreaks.find(nCol) != maColManualBreaks.end();
395 SCROW ScTable::GetNextManualBreak(SCROW nRow) const
397 set<SCROW>::const_iterator itr = maRowManualBreaks.lower_bound(nRow);
398 return itr == maRowManualBreaks.end() ? -1 : *itr;
401 void ScTable::RemoveRowPageBreaks(SCROW nStartRow, SCROW nEndRow)
403 using namespace std;
405 if (!ValidRow(nStartRow) || !ValidRow(nEndRow))
406 return;
408 set<SCROW>::iterator low = maRowPageBreaks.lower_bound(nStartRow);
409 set<SCROW>::iterator high = maRowPageBreaks.upper_bound(nEndRow);
410 maRowPageBreaks.erase(low, high);
413 void ScTable::RemoveRowBreak(SCROW nRow, bool bPage, bool bManual)
415 if (!ValidRow(nRow))
416 return;
418 if (bPage)
419 maRowPageBreaks.erase(nRow);
421 if (bManual)
423 maRowManualBreaks.erase(nRow);
424 InvalidatePageBreaks();
428 void ScTable::RemoveColBreak(SCCOL nCol, bool bPage, bool bManual)
430 if (!ValidCol(nCol))
431 return;
433 if (bPage)
434 maColPageBreaks.erase(nCol);
436 if (bManual)
438 maColManualBreaks.erase(nCol);
439 InvalidatePageBreaks();
443 void ScTable::SetRowBreak(SCROW nRow, bool bPage, bool bManual)
445 if (!ValidRow(nRow))
446 return;
448 if (bPage)
449 maRowPageBreaks.insert(nRow);
451 if (bManual)
453 maRowManualBreaks.insert(nRow);
454 InvalidatePageBreaks();
458 void ScTable::SetColBreak(SCCOL nCol, bool bPage, bool bManual)
460 if (!ValidCol(nCol))
461 return;
463 if (bPage)
464 maColPageBreaks.insert(nCol);
466 if (bManual)
468 maColManualBreaks.insert(nCol);
469 InvalidatePageBreaks();
473 Sequence<TablePageBreakData> ScTable::GetRowBreakData() const
475 using ::std::copy;
476 using ::std::inserter;
478 set<SCROW> aRowBreaks = maRowPageBreaks;
479 copy(maRowManualBreaks.begin(), maRowManualBreaks.end(), inserter(aRowBreaks, aRowBreaks.begin()));
481 set<SCROW>::const_iterator itr = aRowBreaks.begin(), itrEnd = aRowBreaks.end();
482 Sequence<TablePageBreakData> aSeq(aRowBreaks.size());
484 for (sal_Int32 i = 0; itr != itrEnd; ++itr, ++i)
486 SCROW nRow = *itr;
487 TablePageBreakData aData;
488 aData.Position = nRow;
489 aData.ManualBreak = HasRowManualBreak(nRow);
490 aSeq[i] = aData;
493 return aSeq;
496 bool ScTable::RowHidden(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
498 if (!ValidRow(nRow))
500 if (pFirstRow)
501 *pFirstRow = nRow;
502 if (pLastRow)
503 *pLastRow = nRow;
504 return true;
507 ScFlatBoolRowSegments::RangeData aData;
508 if (!mpHiddenRows->getRangeData(nRow, aData))
510 // search failed.
511 if (pFirstRow)
512 *pFirstRow = nRow;
513 if (pLastRow)
514 *pLastRow = nRow;
515 return true;
518 if (pFirstRow)
519 *pFirstRow = aData.mnRow1;
520 if (pLastRow)
521 *pLastRow = aData.mnRow2;
523 return aData.mbValue;
526 bool ScTable::RowHiddenLeaf(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
528 if (!ValidRow(nRow))
530 if (pFirstRow)
531 *pFirstRow = nRow;
532 if (pLastRow)
533 *pLastRow = nRow;
534 return true;
537 ScFlatBoolRowSegments::RangeData aData;
538 if (!mpHiddenRows->getRangeDataLeaf(nRow, aData))
540 // search failed.
541 if (pFirstRow)
542 *pFirstRow = nRow;
543 if (pLastRow)
544 *pLastRow = nRow;
545 return true;
548 if (pFirstRow)
549 *pFirstRow = aData.mnRow1;
550 if (pLastRow)
551 *pLastRow = aData.mnRow2;
553 return aData.mbValue;
556 bool ScTable::HasHiddenRows(SCROW nStartRow, SCROW nEndRow) const
558 SCROW nRow = nStartRow;
559 while (nRow <= nEndRow)
561 SCROW nLastRow = -1;
562 bool bHidden = RowHidden(nRow, NULL, &nLastRow);
563 if (bHidden)
564 return true;
566 nRow = nLastRow + 1;
568 return false;
571 bool ScTable::ColHidden(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const
573 if (!ValidCol(nCol))
574 return true;
576 ScFlatBoolColSegments::RangeData aData;
577 if (!mpHiddenCols->getRangeData(nCol, aData))
578 return true;
580 if (pFirstCol)
581 *pFirstCol = aData.mnCol1;
582 if (pLastCol)
583 *pLastCol = aData.mnCol2;
585 return aData.mbValue;
588 bool ScTable::SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden)
590 bool bChanged = false;
591 if (bHidden)
592 bChanged = mpHiddenRows->setTrue(nStartRow, nEndRow);
593 else
594 bChanged = mpHiddenRows->setFalse(nStartRow, nEndRow);
596 if (bChanged)
598 if (IsStreamValid())
599 SetStreamValid(false);
602 return bChanged;
605 bool ScTable::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, bool bHidden)
607 bool bChanged = false;
608 if (bHidden)
609 bChanged = mpHiddenCols->setTrue(nStartCol, nEndCol);
610 else
611 bChanged = mpHiddenCols->setFalse(nStartCol, nEndCol);
613 if (bChanged)
615 if (IsStreamValid())
616 SetStreamValid(false);
619 return bChanged;
622 void ScTable::CopyColHidden(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol)
624 SCCOL nCol = nStartCol;
625 while (nCol <= nEndCol)
627 SCCOL nLastCol;
628 bool bHidden = rTable.ColHidden(nCol, NULL, &nLastCol);
629 if (nLastCol > nEndCol)
630 nLastCol = nEndCol;
632 SetColHidden(nCol, nLastCol, bHidden);
633 nCol = nLastCol + 1;
637 void ScTable::CopyRowHidden(ScTable& rTable, SCROW nStartRow, SCROW nEndRow)
639 SCROW nRow = nStartRow;
640 while (nRow <= nEndRow)
642 SCROW nLastRow = -1;
643 bool bHidden = rTable.RowHidden(nRow, NULL, &nLastRow);
644 if (nLastRow > nEndRow)
645 nLastRow = nEndRow;
646 SetRowHidden(nRow, nLastRow, bHidden);
647 nRow = nLastRow + 1;
651 void ScTable::CopyRowHeight(ScTable& rSrcTable, SCROW nStartRow, SCROW nEndRow, SCROW nSrcOffset)
653 SCROW nRow = nStartRow;
654 ScFlatUInt16RowSegments::RangeData aSrcData;
655 while (nRow <= nEndRow)
657 if (!rSrcTable.mpRowHeights->getRangeData(nRow + nSrcOffset, aSrcData))
658 // Something is wrong !
659 return;
661 SCROW nLastRow = aSrcData.mnRow2 - nSrcOffset;
662 if (nLastRow > nEndRow)
663 nLastRow = nEndRow;
665 mpRowHeights->setValue(nRow, nLastRow, aSrcData.mnValue);
666 nRow = nLastRow + 1;
670 SCROW ScTable::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow) const
672 SCROW nRow = nStartRow;
673 ScFlatBoolRowSegments::RangeData aData;
674 while (nRow <= nEndRow)
676 if (!ValidRow(nRow))
677 break;
679 if (!mpHiddenRows->getRangeData(nRow, aData))
680 // failed to get range data.
681 break;
683 if (!aData.mbValue)
684 // visible row found
685 return nRow;
687 nRow = aData.mnRow2 + 1;
690 return ::std::numeric_limits<SCROW>::max();
693 SCROW ScTable::LastVisibleRow(SCROW nStartRow, SCROW nEndRow) const
695 SCROW nRow = nEndRow;
696 ScFlatBoolRowSegments::RangeData aData;
697 while (nRow >= nStartRow)
699 if (!ValidRow(nRow))
700 break;
702 if (!mpHiddenRows->getRangeData(nRow, aData))
703 // failed to get range data.
704 break;
706 if (!aData.mbValue)
707 // visible row found
708 return nRow;
710 nRow = aData.mnRow1 - 1;
713 return ::std::numeric_limits<SCROW>::max();
716 SCROW ScTable::CountVisibleRows(SCROW nStartRow, SCROW nEndRow) const
718 SCROW nCount = 0;
719 SCROW nRow = nStartRow;
720 ScFlatBoolRowSegments::RangeData aData;
721 while (nRow <= nEndRow)
723 if (!mpHiddenRows->getRangeData(nRow, aData))
724 break;
726 if (aData.mnRow2 > nEndRow)
727 aData.mnRow2 = nEndRow;
729 if (!aData.mbValue)
730 nCount += aData.mnRow2 - nRow + 1;
732 nRow = aData.mnRow2 + 1;
734 return nCount;
737 sal_uInt32 ScTable::GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow, bool bHiddenAsZero ) const
739 sal_uInt32 nHeight = 0;
740 SCROW nRow = nStartRow;
741 ScFlatBoolRowSegments::RangeData aData;
742 while (nRow <= nEndRow)
744 if (!mpHiddenRows->getRangeData(nRow, aData))
745 break;
747 if (aData.mnRow2 > nEndRow)
748 aData.mnRow2 = nEndRow;
750 if ( !( bHiddenAsZero && aData.mbValue ) )
751 // visible row range.
752 nHeight += mpRowHeights->getSumValue(nRow, aData.mnRow2);
754 nRow = aData.mnRow2 + 1;
757 return nHeight;
760 SCCOLROW ScTable::LastHiddenColRow(SCCOLROW nPos, bool bCol) const
762 if (bCol)
764 SCCOL nCol = static_cast<SCCOL>(nPos);
765 if (ColHidden(nCol))
767 for (SCCOL i = nCol+1; i <= MAXCOL; ++i)
769 if (!ColHidden(nCol))
770 return nCol - 1;
774 else
776 SCROW nRow = static_cast<SCROW>(nPos);
777 SCROW nLastRow;
778 if (RowHidden(nRow, NULL, &nLastRow))
779 return static_cast<SCCOLROW>(nLastRow);
781 return ::std::numeric_limits<SCCOLROW>::max();
784 bool ScTable::RowFiltered(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
786 if (!ValidRow(nRow))
787 return false;
789 ScFlatBoolRowSegments::RangeData aData;
790 if (!mpFilteredRows->getRangeData(nRow, aData))
791 // search failed.
792 return false;
794 if (pFirstRow)
795 *pFirstRow = aData.mnRow1;
796 if (pLastRow)
797 *pLastRow = aData.mnRow2;
799 return aData.mbValue;
802 bool ScTable::ColFiltered(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const
804 if (!ValidCol(nCol))
805 return false;
807 ScFlatBoolColSegments::RangeData aData;
808 if (!mpFilteredCols->getRangeData(nCol, aData))
809 // search failed.
810 return false;
812 if (pFirstCol)
813 *pFirstCol = aData.mnCol1;
814 if (pLastCol)
815 *pLastCol = aData.mnCol2;
817 return aData.mbValue;
820 bool ScTable::HasFilteredRows(SCROW nStartRow, SCROW nEndRow) const
822 SCROW nRow = nStartRow;
823 while (nRow <= nEndRow)
825 SCROW nLastRow = nRow;
826 bool bFiltered = RowFiltered(nRow, NULL, &nLastRow);
827 if (bFiltered)
828 return true;
830 nRow = nLastRow + 1;
832 return false;
835 void ScTable::CopyColFiltered(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol)
837 SCCOL nCol = nStartCol;
838 while (nCol <= nEndCol)
840 SCCOL nLastCol = -1;
841 bool bFiltered = rTable.ColFiltered(nCol, NULL, &nLastCol);
842 if (nLastCol > nEndCol)
843 nLastCol = nEndCol;
845 SetColFiltered(nCol, nLastCol, bFiltered);
846 nCol = nLastCol + 1;
850 void ScTable::CopyRowFiltered(ScTable& rTable, SCROW nStartRow, SCROW nEndRow)
852 SCROW nRow = nStartRow;
853 while (nRow <= nEndRow)
855 SCROW nLastRow = -1;
856 bool bFiltered = rTable.RowFiltered(nRow, NULL, &nLastRow);
857 if (nLastRow > nEndRow)
858 nLastRow = nEndRow;
859 SetRowFiltered(nRow, nLastRow, bFiltered);
860 nRow = nLastRow + 1;
864 void ScTable::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, bool bFiltered)
866 if (bFiltered)
867 mpFilteredRows->setTrue(nStartRow, nEndRow);
868 else
869 mpFilteredRows->setFalse(nStartRow, nEndRow);
872 void ScTable::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, bool bFiltered)
874 if (bFiltered)
875 mpFilteredCols->setTrue(nStartCol, nEndCol);
876 else
877 mpFilteredCols->setFalse(nStartCol, nEndCol);
880 SCROW ScTable::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const
882 SCROW nRow = nStartRow;
883 ScFlatBoolRowSegments::RangeData aData;
884 while (nRow <= nEndRow)
886 if (!ValidRow(nRow))
887 break;
889 if (!mpFilteredRows->getRangeData(nRow, aData))
890 // failed to get range data.
891 break;
893 if (!aData.mbValue)
894 // non-filtered row found
895 return nRow;
897 nRow = aData.mnRow2 + 1;
900 return ::std::numeric_limits<SCROW>::max();
903 SCROW ScTable::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const
905 SCROW nRow = nEndRow;
906 ScFlatBoolRowSegments::RangeData aData;
907 while (nRow >= nStartRow)
909 if (!ValidRow(nRow))
910 break;
912 if (!mpFilteredRows->getRangeData(nRow, aData))
913 // failed to get range data.
914 break;
916 if (!aData.mbValue)
917 // non-filtered row found
918 return nRow;
920 nRow = aData.mnRow1 - 1;
923 return ::std::numeric_limits<SCROW>::max();
926 SCROW ScTable::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow) const
928 SCROW nCount = 0;
929 SCROW nRow = nStartRow;
930 ScFlatBoolRowSegments::RangeData aData;
931 while (nRow <= nEndRow)
933 if (!mpFilteredRows->getRangeData(nRow, aData))
934 break;
936 if (aData.mnRow2 > nEndRow)
937 aData.mnRow2 = nEndRow;
939 if (!aData.mbValue)
940 nCount += aData.mnRow2 - nRow + 1;
942 nRow = aData.mnRow2 + 1;
944 return nCount;
947 bool ScTable::IsManualRowHeight(SCROW nRow) const
949 return (pRowFlags->GetValue(nRow) & CR_MANUALSIZE) != 0;
952 namespace {
954 void lcl_syncFlags(ScFlatBoolColSegments& rColSegments, ScFlatBoolRowSegments& rRowSegments,
955 sal_uInt8* pColFlags, ScBitMaskCompressedArray< SCROW, sal_uInt8>* pRowFlags, const sal_uInt8 nFlagMask)
957 using ::sal::static_int_cast;
959 sal_uInt8 nFlagMaskComplement = static_int_cast<sal_uInt8>(~nFlagMask);
961 pRowFlags->AndValue(0, MAXROW, nFlagMaskComplement);
962 for (SCCOL i = 0; i <= MAXCOL; ++i)
963 pColFlags[i] &= nFlagMaskComplement;
966 // row hidden flags.
968 SCROW nRow = 0;
969 ScFlatBoolRowSegments::RangeData aData;
970 while (nRow <= MAXROW)
972 if (!rRowSegments.getRangeData(nRow, aData))
973 break;
975 if (aData.mbValue)
976 pRowFlags->OrValue(nRow, aData.mnRow2, nFlagMask);
978 nRow = aData.mnRow2 + 1;
983 // column hidden flags.
985 SCCOL nCol = 0;
986 ScFlatBoolColSegments::RangeData aData;
987 while (nCol <= MAXCOL)
989 if (!rColSegments.getRangeData(nCol, aData))
990 break;
992 if (aData.mbValue)
994 for (SCCOL i = nCol; i <= aData.mnCol2; ++i)
995 pColFlags[i] |= nFlagMask;
998 nCol = aData.mnCol2 + 1;
1005 void ScTable::SyncColRowFlags()
1007 using ::sal::static_int_cast;
1009 sal_uInt8 nManualBreakComplement = static_int_cast<sal_uInt8>(~CR_MANUALBREAK);
1011 // Manual breaks.
1012 pRowFlags->AndValue(0, MAXROW, nManualBreakComplement);
1013 for (SCCOL i = 0; i <= MAXCOL; ++i)
1014 pColFlags[i] &= nManualBreakComplement;
1016 if (!maRowManualBreaks.empty())
1018 for (set<SCROW>::const_iterator itr = maRowManualBreaks.begin(), itrEnd = maRowManualBreaks.end();
1019 itr != itrEnd; ++itr)
1020 pRowFlags->OrValue(*itr, CR_MANUALBREAK);
1023 if (!maColManualBreaks.empty())
1025 for (set<SCCOL>::const_iterator itr = maColManualBreaks.begin(), itrEnd = maColManualBreaks.end();
1026 itr != itrEnd; ++itr)
1027 pColFlags[*itr] |= CR_MANUALBREAK;
1030 // Hidden flags.
1031 lcl_syncFlags(*mpHiddenCols, *mpHiddenRows, pColFlags, pRowFlags, CR_HIDDEN);
1032 lcl_syncFlags(*mpFilteredCols, *mpFilteredRows, pColFlags, pRowFlags, CR_FILTERED);
1035 void ScTable::SetPageSize( const Size& rSize )
1037 if ( rSize.Width() != 0 && rSize.Height() != 0 )
1039 if (aPageSizeTwips != rSize)
1040 InvalidatePageBreaks();
1042 bPageSizeValid = true;
1043 aPageSizeTwips = rSize;
1045 else
1046 bPageSizeValid = false;
1049 bool ScTable::IsProtected() const
1051 return pTabProtection.get() && pTabProtection->isProtected();
1054 void ScTable::SetProtection(const ScTableProtection* pProtect)
1056 if (pProtect)
1057 pTabProtection.reset(new ScTableProtection(*pProtect));
1058 else
1059 pTabProtection.reset();
1061 if (IsStreamValid())
1062 SetStreamValid(false);
1065 ScTableProtection* ScTable::GetProtection()
1067 return pTabProtection.get();
1070 Size ScTable::GetPageSize() const
1072 if ( bPageSizeValid )
1073 return aPageSizeTwips;
1074 else
1075 return Size(); // blank
1078 void ScTable::SetRepeatArea( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
1080 // #i117952# page break calculation uses these values (set from ScPrintFunc), not pRepeatColRange/pRepeatRowRange
1081 if ( nStartCol != nRepeatStartX || nEndCol != nRepeatEndX || nStartRow != nRepeatStartY || nEndRow != nRepeatEndY )
1082 InvalidatePageBreaks();
1084 nRepeatStartX = nStartCol;
1085 nRepeatEndX = nEndCol;
1086 nRepeatStartY = nStartRow;
1087 nRepeatEndY = nEndRow;
1090 void ScTable::StartListening( const ScAddress& rAddress, SvtListener* pListener )
1092 if (!ValidCol(rAddress.Col()))
1093 return;
1095 aCol[rAddress.Col()].StartListening( *pListener, rAddress.Row() );
1098 void ScTable::EndListening( const ScAddress& rAddress, SvtListener* pListener )
1100 if (!ValidCol(rAddress.Col()))
1101 return;
1103 aCol[rAddress.Col()].EndListening( *pListener, rAddress.Row() );
1106 void ScTable::StartListening( sc::StartListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener )
1108 if (!ValidCol(nCol))
1109 return;
1111 aCol[nCol].StartListening(rCxt, nRow, rListener);
1114 void ScTable::EndListening( sc::EndListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener )
1116 if (!ValidCol(nCol))
1117 return;
1119 aCol[nCol].EndListening(rCxt, nRow, rListener);
1122 void ScTable::SetPageStyle( const OUString& rName )
1124 if ( aPageStyle != rName )
1126 OUString aStrNew = rName;
1127 SfxStyleSheetBasePool* pStylePool = pDocument->GetStyleSheetPool();
1128 SfxStyleSheetBase* pNewStyle = pStylePool->Find( aStrNew, SFX_STYLE_FAMILY_PAGE );
1130 if ( !pNewStyle )
1132 aStrNew = ScGlobal::GetRscString(STR_STYLENAME_STANDARD);
1133 pNewStyle = pStylePool->Find( aStrNew, SFX_STYLE_FAMILY_PAGE );
1136 if ( aPageStyle != aStrNew )
1138 SfxStyleSheetBase* pOldStyle = pStylePool->Find( aPageStyle, SFX_STYLE_FAMILY_PAGE );
1140 if ( pOldStyle && pNewStyle )
1142 SfxItemSet& rOldSet = pOldStyle->GetItemSet();
1143 SfxItemSet& rNewSet = pNewStyle->GetItemSet();
1144 const sal_uInt16 nOldScale = GET_SCALEVALUE(rOldSet,ATTR_PAGE_SCALE);
1145 const sal_uInt16 nOldScaleToPages = GET_SCALEVALUE(rOldSet,ATTR_PAGE_SCALETOPAGES);
1146 const sal_uInt16 nNewScale = GET_SCALEVALUE(rNewSet,ATTR_PAGE_SCALE);
1147 const sal_uInt16 nNewScaleToPages = GET_SCALEVALUE(rNewSet,ATTR_PAGE_SCALETOPAGES);
1149 if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
1150 InvalidateTextWidth(NULL, NULL, false, false);
1153 if ( pNewStyle ) // also without the old one (for UpdateStdNames)
1154 aPageStyle = aStrNew;
1156 if (IsStreamValid())
1157 SetStreamValid(false);
1162 void ScTable::PageStyleModified( const OUString& rNewName )
1164 aPageStyle = rNewName;
1165 InvalidateTextWidth(NULL, NULL, false, false); // don't know what was in the style before
1168 void ScTable::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
1169 bool bNumFormatChanged, bool bBroadcast )
1171 if ( pAdrFrom && !pAdrTo )
1173 // Special case: only process the "from" cell.
1174 SCCOL nCol = pAdrFrom->Col();
1175 SCROW nRow = pAdrFrom->Row();
1176 ScColumn& rCol = aCol[nCol];
1177 ScRefCellValue aCell = rCol.GetCellValue(nRow);
1178 if (aCell.isEmpty())
1179 return;
1181 rCol.SetTextWidth(nRow, TEXTWIDTH_DIRTY);
1183 if ( bNumFormatChanged )
1184 rCol.SetScriptType(nRow, SvtScriptType::UNKNOWN);
1186 if ( bBroadcast )
1187 { // Only with CalcAsShown
1188 switch (aCell.meType)
1190 case CELLTYPE_VALUE :
1191 rCol.Broadcast(nRow);
1192 break;
1193 case CELLTYPE_FORMULA :
1194 aCell.mpFormula->SetDirty();
1195 break;
1196 default:
1198 // added to avoid warnings
1203 return;
1206 const SCCOL nCol1 = pAdrFrom ? pAdrFrom->Col() : 0;
1207 const SCROW nRow1 = pAdrFrom ? pAdrFrom->Row() : 0;
1208 const SCCOL nCol2 = pAdrTo ? pAdrTo->Col() : MAXCOL;
1209 const SCROW nRow2 = pAdrTo ? pAdrTo->Row() : MAXROW;
1211 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
1213 ScColumnTextWidthIterator aIter(aCol[nCol], nRow1, nRow2);
1215 for (; aIter.hasCell(); aIter.next())
1217 SCROW nRow = aIter.getPos();
1218 aIter.setValue(TEXTWIDTH_DIRTY);
1219 ScRefCellValue aCell = aCol[nCol].GetCellValue(nRow);
1220 if (aCell.isEmpty())
1221 continue;
1223 if ( bNumFormatChanged )
1224 aCol[nCol].SetScriptType(nRow, SvtScriptType::UNKNOWN);
1226 if ( bBroadcast )
1227 { // Only with CalcAsShown
1228 switch (aCell.meType)
1230 case CELLTYPE_VALUE :
1231 aCol[nCol].Broadcast(nRow);
1232 break;
1233 case CELLTYPE_FORMULA :
1234 aCell.mpFormula->SetDirty();
1235 break;
1236 default:
1238 // added to avoid warnings
1246 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */