re-enabled user-defined numeric fields for dBase export
[LibreOffice.git] / sc / source / core / data / table5.cxx
blobed150867ee6d8fb8f8e35d69a80e03d76db4d36d
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"
42 #include <com/sun/star/sheet/TablePageBreakData.hpp>
44 #include <algorithm>
45 #include <limits>
47 using ::com::sun::star::uno::Sequence;
48 using ::com::sun::star::sheet::TablePageBreakData;
49 using ::std::set;
51 // STATIC DATA -----------------------------------------------------------
53 #define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue()
56 void ScTable::UpdatePageBreaks( const ScRange* pUserArea )
58 if ( pDocument->IsImportingXML() )
59 return;
61 // pUserArea != NULL -> print area is specified. We need to force-update
62 // the page breaks.
64 if (!pUserArea)
66 if (!bPageSizeValid)
67 return;
69 if (mbPageBreaksValid)
70 return;
73 SfxStyleSheetBase* pStyle = pDocument->GetStyleSheetPool()->
74 Find( aPageStyle, SFX_STYLE_FAMILY_PAGE );
75 if ( !pStyle )
77 OSL_FAIL("UpdatePageBreaks: Style not found");
78 return;
80 SfxItemSet* pStyleSet = &pStyle->GetItemSet();
81 const SfxPoolItem* pItem;
83 SCCOL nX;
84 SCCOL nStartCol = 0;
85 SCROW nStartRow = 0;
86 SCCOL nEndCol = MAXCOL;
87 SCROW nEndRow = MAXROW;
88 if (pUserArea)
90 nStartCol = pUserArea->aStart.Col();
91 nStartRow = pUserArea->aStart.Row();
92 nEndCol = pUserArea->aEnd.Col();
93 nEndRow = pUserArea->aEnd.Row();
95 else
97 sal_uInt16 nAreaCount = GetPrintRangeCount();
98 if ( nAreaCount > 1 )
100 // bei mehreren Bereichen nichts anzeigen:
102 for (nX=0; nX<MAXCOL; nX++)
103 RemoveColBreak(nX, true, false);
105 RemoveRowPageBreaks(0, MAXROW-1);
107 return;
109 else if ( nAreaCount == 1 )
111 const ScRange* pArea = GetPrintRange( 0 );
112 if (pArea)
114 nStartCol = pArea->aStart.Col();
115 nStartRow = pArea->aStart.Row();
116 nEndCol = pArea->aEnd.Col();
117 nEndRow = pArea->aEnd.Row();
119 } // sonst alles
122 // get bSkipColBreaks/bSkipRowBreaks flags:
124 bool bSkipColBreaks = false;
125 bool bSkipRowBreaks = false;
127 if ( pStyleSet->GetItemState( ATTR_PAGE_SCALETOPAGES, false, &pItem ) == SFX_ITEM_SET )
129 OSL_ENSURE( pItem->ISA(SfxUInt16Item), "invalid Item" );
130 bSkipColBreaks = bSkipRowBreaks = ( ((const SfxUInt16Item*)pItem)->GetValue() > 0 );
133 if ( !bSkipColBreaks && pStyleSet->GetItemState(ATTR_PAGE_SCALETO, false, &pItem) == SFX_ITEM_SET )
135 // #i54993# when fitting to width or height, ignore only manual breaks in that direction
136 const ScPageScaleToItem* pScaleToItem = static_cast<const ScPageScaleToItem*>(pItem);
137 if ( pScaleToItem->GetWidth() > 0 )
138 bSkipColBreaks = true;
139 if ( pScaleToItem->GetHeight() > 0 )
140 bSkipRowBreaks = true;
143 //--------------------------------------------------------------------------
145 long nPageSizeX = aPageSizeTwips.Width();
146 long nPageSizeY = aPageSizeTwips.Height();
148 // Anfang: Breaks loeschen
150 for (nX=0; nX<nStartCol; nX++)
151 RemoveColBreak(nX, true, false);
152 RemoveRowPageBreaks(0, nStartRow-1);
154 if (nStartCol > 0)
155 SetColBreak(nStartCol, true, false); // AREABREAK
156 if (nStartRow > 0)
157 SetRowBreak(nStartRow, true, false); // AREABREAK
159 // Mittelteil: Breaks verteilen
161 bool bRepeatCol = ( nRepeatStartX != SCCOL_REPEAT_NONE );
162 bool bColFound = false;
163 long nSizeX = 0;
164 for (nX=nStartCol; nX<=nEndCol; nX++)
166 bool bStartOfPage = false;
167 long nThisX = ColHidden(nX) ? 0 : pColWidth[nX];
168 bool bManualBreak = HasColManualBreak(nX);
169 if ( (nSizeX+nThisX > nPageSizeX) || (bManualBreak && !bSkipColBreaks) )
171 SetColBreak(nX, true, false);
172 nSizeX = 0;
173 bStartOfPage = true;
175 else if (nX != nStartCol)
176 RemoveColBreak(nX, true, false);
177 else
178 bStartOfPage = true;
180 if ( bStartOfPage && bRepeatCol && nX>nRepeatStartX && !bColFound )
182 // subtract size of repeat columns from page size
183 for (SCCOL i=nRepeatStartX; i<=nRepeatEndX; i++)
184 nPageSizeX -= ColHidden(i) ? 0 : pColWidth[i];
185 while (nX<=nRepeatEndX)
186 RemoveColBreak(++nX, true, false);
187 bColFound = true;
190 nSizeX += nThisX;
193 // Remove all page breaks in range.
194 RemoveRowPageBreaks(nStartRow+1, nEndRow);
196 // And set new page breaks.
197 bool bRepeatRow = ( nRepeatStartY != SCROW_REPEAT_NONE );
198 bool bRowFound = false;
199 long nSizeY = 0;
200 ScFlatBoolRowSegments::ForwardIterator aIterHidden(*mpHiddenRows);
201 ScFlatUInt16RowSegments::ForwardIterator aIterHeights(*mpRowHeights);
202 SCROW nNextManualBreak = GetNextManualBreak(nStartRow); // -1 => no more manual breaks
203 for (SCROW nY = nStartRow; nY <= nEndRow; ++nY)
205 bool bStartOfPage = false;
206 bool bThisRowHidden = false;
207 aIterHidden.getValue(nY, bThisRowHidden);
208 long nThisY = 0;
209 if (!bThisRowHidden)
211 sal_uInt16 nTmp;
212 aIterHeights.getValue(nY, nTmp);
213 nThisY = static_cast<long>(nTmp);
216 bool bManualBreak = false;
217 if (nNextManualBreak >= 0)
219 bManualBreak = (nY == nNextManualBreak);
220 if (nY >= nNextManualBreak)
221 // Query the next menual break position.
222 nNextManualBreak = GetNextManualBreak(nY+1);
225 if ( (nSizeY+nThisY > nPageSizeY) || (bManualBreak && !bSkipRowBreaks) )
227 SetRowBreak(nY, true, false);
228 nSizeY = 0;
229 bStartOfPage = true;
231 else if (nY != nStartRow)
232 ; // page break already removed
233 else
234 bStartOfPage = true;
236 if ( bStartOfPage && bRepeatRow && nY>nRepeatStartY && !bRowFound )
238 // subtract size of repeat rows from page size
239 unsigned long nHeights = GetTotalRowHeight(nRepeatStartY, nRepeatEndY);
240 #if OSL_DEBUG_LEVEL > 0
241 if (nHeights == ::std::numeric_limits<unsigned long>::max())
242 OSL_FAIL("ScTable::UpdatePageBreaks: row heights overflow");
243 #endif
244 nPageSizeY -= nHeights;
245 if (nY <= nRepeatEndY)
246 RemoveRowPageBreaks(nY, nRepeatEndY);
247 bRowFound = true;
250 if (bThisRowHidden)
252 // Hidden row range. Skip them unless there is a manual break.
253 SCROW nLastCommon = aIterHidden.getLastPos();
254 if (nNextManualBreak >= 0)
255 nLastCommon = ::std::min(nLastCommon, nNextManualBreak-1);
256 nY = nLastCommon;
258 else
260 // Visible row range.
262 SCROW nLastHidden = aIterHidden.getLastPos();
263 SCROW nLastHeight = aIterHeights.getLastPos();
264 SCROW nLastCommon = ::std::min(nLastHidden, nLastHeight);
265 if (nNextManualBreak >= 0)
266 nLastCommon = ::std::min(nLastCommon, nNextManualBreak-1);
268 if (nLastCommon > nY)
270 long nMaxMultiple = static_cast<long>(nLastCommon - nY);
271 long nMultiple = (nPageSizeY - nSizeY) / nThisY;
272 if (nMultiple > nMaxMultiple)
273 nMultiple = nMaxMultiple;
274 if (nMultiple > 1)
276 nSizeY += nThisY * (nMultiple - 1);
277 nY += nMultiple - 1;
282 nSizeY += nThisY;
285 // Ende: Breaks loeschen
287 if (nEndCol < MAXCOL)
289 SetColBreak(nEndCol+1, true, false); // AREABREAK
290 for (nX=nEndCol+2; nX<=MAXCOL; nX++)
291 RemoveColBreak(nX, true, false);
293 if (nEndRow < MAXROW)
295 SetRowBreak(nEndRow+1, true, false); // AREABREAK
296 if (nEndRow+2 <= MAXROW)
297 RemoveRowPageBreaks(nEndRow+2, MAXROW);
299 mbPageBreaksValid = !pUserArea; // #i116881# the valid flag can only apply to the "no user area" case
302 void ScTable::RemoveManualBreaks()
304 maRowManualBreaks.clear();
305 maColManualBreaks.clear();
306 InvalidatePageBreaks();
308 if (IsStreamValid())
309 SetStreamValid(false);
312 bool ScTable::HasManualBreaks() const
314 return !maRowManualBreaks.empty() || !maColManualBreaks.empty();
317 void ScTable::SetRowManualBreaks( const ::std::set<SCROW>& rBreaks )
319 maRowManualBreaks = rBreaks;
320 InvalidatePageBreaks();
321 if (IsStreamValid())
322 SetStreamValid(false);
325 void ScTable::SetColManualBreaks( const ::std::set<SCCOL>& rBreaks )
327 maColManualBreaks = rBreaks;
328 InvalidatePageBreaks();
329 if (IsStreamValid())
330 SetStreamValid(false);
333 void ScTable::GetAllRowBreaks(set<SCROW>& rBreaks, bool bPage, bool bManual) const
335 if (bPage)
336 rBreaks = maRowPageBreaks;
338 if (bManual)
340 using namespace std;
341 copy(maRowManualBreaks.begin(), maRowManualBreaks.end(), inserter(rBreaks, rBreaks.begin()));
345 void ScTable::GetAllColBreaks(set<SCCOL>& rBreaks, bool bPage, bool bManual) const
347 if (bPage)
348 rBreaks = maColPageBreaks;
350 if (bManual)
352 using namespace std;
353 copy(maColManualBreaks.begin(), maColManualBreaks.end(), inserter(rBreaks, rBreaks.begin()));
357 bool ScTable::HasRowPageBreak(SCROW nRow) const
359 if (!ValidRow(nRow))
360 return false;
362 return maRowPageBreaks.find(nRow) != maRowPageBreaks.end();
365 bool ScTable::HasColPageBreak(SCCOL nCol) const
367 if (!ValidCol(nCol))
368 return false;
370 return maColPageBreaks.find(nCol) != maColPageBreaks.end();
373 bool ScTable::HasRowManualBreak(SCROW nRow) const
375 if (!ValidRow(nRow))
376 return false;
378 return maRowManualBreaks.find(nRow) != maRowManualBreaks.end();
381 bool ScTable::HasColManualBreak(SCCOL nCol) const
383 if (!ValidCol(nCol))
384 return false;
386 return maColManualBreaks.find(nCol) != maColManualBreaks.end();
389 SCROW ScTable::GetNextManualBreak(SCROW nRow) const
391 set<SCROW>::const_iterator itr = maRowManualBreaks.lower_bound(nRow);
392 return itr == maRowManualBreaks.end() ? -1 : *itr;
395 void ScTable::RemoveRowPageBreaks(SCROW nStartRow, SCROW nEndRow)
397 using namespace std;
399 if (!ValidRow(nStartRow) || !ValidRow(nEndRow))
400 return;
402 set<SCROW>::iterator low = maRowPageBreaks.lower_bound(nStartRow);
403 set<SCROW>::iterator high = maRowPageBreaks.upper_bound(nEndRow);
404 maRowPageBreaks.erase(low, high);
407 void ScTable::RemoveRowBreak(SCROW nRow, bool bPage, bool bManual)
409 if (!ValidRow(nRow))
410 return;
412 if (bPage)
413 maRowPageBreaks.erase(nRow);
415 if (bManual)
417 maRowManualBreaks.erase(nRow);
418 InvalidatePageBreaks();
422 void ScTable::RemoveColBreak(SCCOL nCol, bool bPage, bool bManual)
424 if (!ValidCol(nCol))
425 return;
427 if (bPage)
428 maColPageBreaks.erase(nCol);
430 if (bManual)
432 maColManualBreaks.erase(nCol);
433 InvalidatePageBreaks();
437 void ScTable::SetRowBreak(SCROW nRow, bool bPage, bool bManual)
439 if (!ValidRow(nRow))
440 return;
442 if (bPage)
443 maRowPageBreaks.insert(nRow);
445 if (bManual)
447 maRowManualBreaks.insert(nRow);
448 InvalidatePageBreaks();
452 void ScTable::SetColBreak(SCCOL nCol, bool bPage, bool bManual)
454 if (!ValidCol(nCol))
455 return;
457 if (bPage)
458 maColPageBreaks.insert(nCol);
460 if (bManual)
462 maColManualBreaks.insert(nCol);
463 InvalidatePageBreaks();
467 Sequence<TablePageBreakData> ScTable::GetRowBreakData() const
469 using ::std::copy;
470 using ::std::inserter;
472 set<SCROW> aRowBreaks = maRowPageBreaks;
473 copy(maRowManualBreaks.begin(), maRowManualBreaks.end(), inserter(aRowBreaks, aRowBreaks.begin()));
475 set<SCROW>::const_iterator itr = aRowBreaks.begin(), itrEnd = aRowBreaks.end();
476 Sequence<TablePageBreakData> aSeq(aRowBreaks.size());
478 for (sal_Int32 i = 0; itr != itrEnd; ++itr, ++i)
480 SCROW nRow = *itr;
481 TablePageBreakData aData;
482 aData.Position = nRow;
483 aData.ManualBreak = HasRowManualBreak(nRow);
484 aSeq[i] = aData;
487 return aSeq;
490 bool ScTable::RowHidden(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
492 if (!ValidRow(nRow))
494 if (pFirstRow)
495 *pFirstRow = nRow;
496 if (pLastRow)
497 *pLastRow = nRow;
498 return true;
501 ScFlatBoolRowSegments::RangeData aData;
502 if (!mpHiddenRows->getRangeData(nRow, aData))
504 // search failed.
505 if (pFirstRow)
506 *pFirstRow = nRow;
507 if (pLastRow)
508 *pLastRow = nRow;
509 return true;
512 if (pFirstRow)
513 *pFirstRow = aData.mnRow1;
514 if (pLastRow)
515 *pLastRow = aData.mnRow2;
517 return aData.mbValue;
520 bool ScTable::RowHiddenLeaf(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
522 if (!ValidRow(nRow))
524 if (pFirstRow)
525 *pFirstRow = nRow;
526 if (pLastRow)
527 *pLastRow = nRow;
528 return true;
531 ScFlatBoolRowSegments::RangeData aData;
532 if (!mpHiddenRows->getRangeDataLeaf(nRow, aData))
534 // search failed.
535 if (pFirstRow)
536 *pFirstRow = nRow;
537 if (pLastRow)
538 *pLastRow = nRow;
539 return true;
542 if (pFirstRow)
543 *pFirstRow = aData.mnRow1;
544 if (pLastRow)
545 *pLastRow = aData.mnRow2;
547 return aData.mbValue;
550 bool ScTable::HasHiddenRows(SCROW nStartRow, SCROW nEndRow) const
552 SCROW nRow = nStartRow;
553 while (nRow <= nEndRow)
555 SCROW nLastRow = -1;
556 bool bHidden = RowHidden(nRow, NULL, &nLastRow);
557 if (bHidden)
558 return true;
560 nRow = nLastRow + 1;
562 return false;
565 bool ScTable::ColHidden(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const
567 if (!ValidCol(nCol))
568 return true;
570 ScFlatBoolColSegments::RangeData aData;
571 if (!mpHiddenCols->getRangeData(nCol, aData))
572 return true;
574 if (pFirstCol)
575 *pFirstCol = aData.mnCol1;
576 if (pLastCol)
577 *pLastCol = aData.mnCol2;
579 return aData.mbValue;
582 bool ScTable::SetRowHidden(SCROW nStartRow, SCROW nEndRow, bool bHidden)
584 bool bChanged = false;
585 if (bHidden)
586 bChanged = mpHiddenRows->setTrue(nStartRow, nEndRow);
587 else
588 bChanged = mpHiddenRows->setFalse(nStartRow, nEndRow);
590 if (bChanged)
592 if (IsStreamValid())
593 SetStreamValid(false);
596 return bChanged;
599 bool ScTable::SetColHidden(SCCOL nStartCol, SCCOL nEndCol, bool bHidden)
601 bool bChanged = false;
602 if (bHidden)
603 bChanged = mpHiddenCols->setTrue(nStartCol, nEndCol);
604 else
605 bChanged = mpHiddenCols->setFalse(nStartCol, nEndCol);
607 if (bChanged)
609 if (IsStreamValid())
610 SetStreamValid(false);
613 return bChanged;
616 void ScTable::CopyColHidden(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol)
618 SCCOL nCol = nStartCol;
619 while (nCol <= nEndCol)
621 SCCOL nLastCol;
622 bool bHidden = rTable.ColHidden(nCol, NULL, &nLastCol);
623 if (nLastCol > nEndCol)
624 nLastCol = nEndCol;
626 SetColHidden(nCol, nLastCol, bHidden);
627 nCol = nLastCol + 1;
631 void ScTable::CopyRowHidden(ScTable& rTable, SCROW nStartRow, SCROW nEndRow)
633 SCROW nRow = nStartRow;
634 while (nRow <= nEndRow)
636 SCROW nLastRow = -1;
637 bool bHidden = rTable.RowHidden(nRow, NULL, &nLastRow);
638 if (nLastRow > nEndRow)
639 nLastRow = nEndRow;
640 SetRowHidden(nRow, nLastRow, bHidden);
641 nRow = nLastRow + 1;
645 void ScTable::CopyRowHeight(ScTable& rSrcTable, SCROW nStartRow, SCROW nEndRow, SCROW nSrcOffset)
647 SCROW nRow = nStartRow;
648 ScFlatUInt16RowSegments::RangeData aSrcData;
649 while (nRow <= nEndRow)
651 if (!rSrcTable.mpRowHeights->getRangeData(nRow + nSrcOffset, aSrcData))
652 // Something is wrong !
653 return;
655 SCROW nLastRow = aSrcData.mnRow2 - nSrcOffset;
656 if (nLastRow > nEndRow)
657 nLastRow = nEndRow;
659 mpRowHeights->setValue(nRow, nLastRow, aSrcData.mnValue);
660 nRow = nLastRow + 1;
664 SCROW ScTable::FirstVisibleRow(SCROW nStartRow, SCROW nEndRow) const
666 SCROW nRow = nStartRow;
667 ScFlatBoolRowSegments::RangeData aData;
668 while (nRow <= nEndRow)
670 if (!ValidRow(nRow))
671 break;
673 if (!mpHiddenRows->getRangeData(nRow, aData))
674 // failed to get range data.
675 break;
677 if (!aData.mbValue)
678 // visible row found
679 return nRow;
681 nRow = aData.mnRow2 + 1;
684 return ::std::numeric_limits<SCROW>::max();
687 SCROW ScTable::LastVisibleRow(SCROW nStartRow, SCROW nEndRow) const
689 SCROW nRow = nEndRow;
690 ScFlatBoolRowSegments::RangeData aData;
691 while (nRow >= nStartRow)
693 if (!ValidRow(nRow))
694 break;
696 if (!mpHiddenRows->getRangeData(nRow, aData))
697 // failed to get range data.
698 break;
700 if (!aData.mbValue)
701 // visible row found
702 return nRow;
704 nRow = aData.mnRow1 - 1;
707 return ::std::numeric_limits<SCROW>::max();
710 SCROW ScTable::CountVisibleRows(SCROW nStartRow, SCROW nEndRow) const
712 SCROW nCount = 0;
713 SCROW nRow = nStartRow;
714 ScFlatBoolRowSegments::RangeData aData;
715 while (nRow <= nEndRow)
717 if (!mpHiddenRows->getRangeData(nRow, aData))
718 break;
720 if (aData.mnRow2 > nEndRow)
721 aData.mnRow2 = nEndRow;
723 if (!aData.mbValue)
724 nCount += aData.mnRow2 - nRow + 1;
726 nRow = aData.mnRow2 + 1;
728 return nCount;
731 sal_uInt32 ScTable::GetTotalRowHeight(SCROW nStartRow, SCROW nEndRow, bool bHiddenAsZero ) const
733 sal_uInt32 nHeight = 0;
734 SCROW nRow = nStartRow;
735 ScFlatBoolRowSegments::RangeData aData;
736 while (nRow <= nEndRow)
738 if (!mpHiddenRows->getRangeData(nRow, aData))
739 break;
741 if (aData.mnRow2 > nEndRow)
742 aData.mnRow2 = nEndRow;
744 if ( !( bHiddenAsZero && aData.mbValue ) )
745 // visible row range.
746 nHeight += mpRowHeights->getSumValue(nRow, aData.mnRow2);
748 nRow = aData.mnRow2 + 1;
751 return nHeight;
754 SCCOLROW ScTable::LastHiddenColRow(SCCOLROW nPos, bool bCol) const
756 if (bCol)
758 SCCOL nCol = static_cast<SCCOL>(nPos);
759 if (ColHidden(nCol))
761 for (SCCOL i = nCol+1; i <= MAXCOL; ++i)
763 if (!ColHidden(nCol))
764 return nCol - 1;
768 else
770 SCROW nRow = static_cast<SCROW>(nPos);
771 SCROW nLastRow;
772 if (RowHidden(nRow, NULL, &nLastRow))
773 return static_cast<SCCOLROW>(nLastRow);
775 return ::std::numeric_limits<SCCOLROW>::max();
778 bool ScTable::RowFiltered(SCROW nRow, SCROW* pFirstRow, SCROW* pLastRow) const
780 if (!ValidRow(nRow))
781 return false;
783 ScFlatBoolRowSegments::RangeData aData;
784 if (!mpFilteredRows->getRangeData(nRow, aData))
785 // search failed.
786 return false;
788 if (pFirstRow)
789 *pFirstRow = aData.mnRow1;
790 if (pLastRow)
791 *pLastRow = aData.mnRow2;
793 return aData.mbValue;
796 bool ScTable::ColFiltered(SCCOL nCol, SCCOL* pFirstCol, SCCOL* pLastCol) const
798 if (!ValidCol(nCol))
799 return false;
801 ScFlatBoolColSegments::RangeData aData;
802 if (!mpFilteredCols->getRangeData(nCol, aData))
803 // search failed.
804 return false;
806 if (pFirstCol)
807 *pFirstCol = aData.mnCol1;
808 if (pLastCol)
809 *pLastCol = aData.mnCol2;
811 return aData.mbValue;
814 bool ScTable::HasFilteredRows(SCROW nStartRow, SCROW nEndRow) const
816 SCROW nRow = nStartRow;
817 while (nRow <= nEndRow)
819 SCROW nLastRow = nRow;
820 bool bFiltered = RowFiltered(nRow, NULL, &nLastRow);
821 if (bFiltered)
822 return true;
824 nRow = nLastRow + 1;
826 return false;
829 void ScTable::CopyColFiltered(ScTable& rTable, SCCOL nStartCol, SCCOL nEndCol)
831 SCCOL nCol = nStartCol;
832 while (nCol <= nEndCol)
834 SCCOL nLastCol;
835 bool bFiltered = rTable.ColFiltered(nCol, NULL, &nLastCol);
836 if (nLastCol > nEndCol)
837 nLastCol = nEndCol;
839 SetColFiltered(nCol, nLastCol, bFiltered);
840 nCol = nLastCol + 1;
844 void ScTable::CopyRowFiltered(ScTable& rTable, SCROW nStartRow, SCROW nEndRow)
846 SCROW nRow = nStartRow;
847 while (nRow <= nEndRow)
849 SCROW nLastRow = -1;
850 bool bFiltered = rTable.RowFiltered(nRow, NULL, &nLastRow);
851 if (nLastRow > nEndRow)
852 nLastRow = nEndRow;
853 SetRowFiltered(nRow, nLastRow, bFiltered);
854 nRow = nLastRow + 1;
858 void ScTable::SetRowFiltered(SCROW nStartRow, SCROW nEndRow, bool bFiltered)
860 if (bFiltered)
861 mpFilteredRows->setTrue(nStartRow, nEndRow);
862 else
863 mpFilteredRows->setFalse(nStartRow, nEndRow);
866 void ScTable::SetColFiltered(SCCOL nStartCol, SCCOL nEndCol, bool bFiltered)
868 if (bFiltered)
869 mpFilteredCols->setTrue(nStartCol, nEndCol);
870 else
871 mpFilteredCols->setFalse(nStartCol, nEndCol);
874 SCROW ScTable::FirstNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const
876 SCROW nRow = nStartRow;
877 ScFlatBoolRowSegments::RangeData aData;
878 while (nRow <= nEndRow)
880 if (!ValidRow(nRow))
881 break;
883 if (!mpFilteredRows->getRangeData(nRow, aData))
884 // failed to get range data.
885 break;
887 if (!aData.mbValue)
888 // non-filtered row found
889 return nRow;
891 nRow = aData.mnRow2 + 1;
894 return ::std::numeric_limits<SCROW>::max();
897 SCROW ScTable::LastNonFilteredRow(SCROW nStartRow, SCROW nEndRow) const
899 SCROW nRow = nEndRow;
900 ScFlatBoolRowSegments::RangeData aData;
901 while (nRow >= nStartRow)
903 if (!ValidRow(nRow))
904 break;
906 if (!mpFilteredRows->getRangeData(nRow, aData))
907 // failed to get range data.
908 break;
910 if (!aData.mbValue)
911 // non-filtered row found
912 return nRow;
914 nRow = aData.mnRow1 - 1;
917 return ::std::numeric_limits<SCROW>::max();
920 SCROW ScTable::CountNonFilteredRows(SCROW nStartRow, SCROW nEndRow) const
922 SCROW nCount = 0;
923 SCROW nRow = nStartRow;
924 ScFlatBoolRowSegments::RangeData aData;
925 while (nRow <= nEndRow)
927 if (!mpFilteredRows->getRangeData(nRow, aData))
928 break;
930 if (aData.mnRow2 > nEndRow)
931 aData.mnRow2 = nEndRow;
933 if (!aData.mbValue)
934 nCount += aData.mnRow2 - nRow + 1;
936 nRow = aData.mnRow2 + 1;
938 return nCount;
941 bool ScTable::IsManualRowHeight(SCROW nRow) const
943 return (pRowFlags->GetValue(nRow) & CR_MANUALSIZE) != 0;
946 namespace {
948 void lcl_syncFlags(ScFlatBoolColSegments& rColSegments, ScFlatBoolRowSegments& rRowSegments,
949 sal_uInt8* pColFlags, ScBitMaskCompressedArray< SCROW, sal_uInt8>* pRowFlags, const sal_uInt8 nFlagMask)
951 using ::sal::static_int_cast;
953 sal_uInt8 nFlagMaskComplement = static_int_cast<sal_uInt8>(~nFlagMask);
955 pRowFlags->AndValue(0, MAXROW, nFlagMaskComplement);
956 for (SCCOL i = 0; i <= MAXCOL; ++i)
957 pColFlags[i] &= nFlagMaskComplement;
960 // row hidden flags.
962 SCROW nRow = 0;
963 ScFlatBoolRowSegments::RangeData aData;
964 while (nRow <= MAXROW)
966 if (!rRowSegments.getRangeData(nRow, aData))
967 break;
969 if (aData.mbValue)
970 pRowFlags->OrValue(nRow, aData.mnRow2, nFlagMask);
972 nRow = aData.mnRow2 + 1;
977 // column hidden flags.
979 SCCOL nCol = 0;
980 ScFlatBoolColSegments::RangeData aData;
981 while (nCol <= MAXCOL)
983 if (!rColSegments.getRangeData(nCol, aData))
984 break;
986 if (aData.mbValue)
988 for (SCCOL i = nCol; i <= aData.mnCol2; ++i)
989 pColFlags[i] |= nFlagMask;
992 nCol = aData.mnCol2 + 1;
999 void ScTable::SyncColRowFlags()
1001 using ::sal::static_int_cast;
1003 sal_uInt8 nManualBreakComplement = static_int_cast<sal_uInt8>(~CR_MANUALBREAK);
1005 // Manual breaks.
1006 pRowFlags->AndValue(0, MAXROW, nManualBreakComplement);
1007 for (SCCOL i = 0; i <= MAXCOL; ++i)
1008 pColFlags[i] &= nManualBreakComplement;
1010 if (!maRowManualBreaks.empty())
1012 for (set<SCROW>::const_iterator itr = maRowManualBreaks.begin(), itrEnd = maRowManualBreaks.end();
1013 itr != itrEnd; ++itr)
1014 pRowFlags->OrValue(*itr, CR_MANUALBREAK);
1017 if (!maColManualBreaks.empty())
1019 for (set<SCCOL>::const_iterator itr = maColManualBreaks.begin(), itrEnd = maColManualBreaks.end();
1020 itr != itrEnd; ++itr)
1021 pColFlags[*itr] |= CR_MANUALBREAK;
1024 // Hidden flags.
1025 lcl_syncFlags(*mpHiddenCols, *mpHiddenRows, pColFlags, pRowFlags, CR_HIDDEN);
1026 lcl_syncFlags(*mpFilteredCols, *mpFilteredRows, pColFlags, pRowFlags, CR_FILTERED);
1029 void ScTable::SetPageSize( const Size& rSize )
1031 if ( rSize.Width() != 0 && rSize.Height() != 0 )
1033 if (aPageSizeTwips != rSize)
1034 InvalidatePageBreaks();
1036 bPageSizeValid = true;
1037 aPageSizeTwips = rSize;
1039 else
1040 bPageSizeValid = false;
1043 bool ScTable::IsProtected() const
1045 return pTabProtection.get() && pTabProtection->isProtected();
1048 void ScTable::SetProtection(const ScTableProtection* pProtect)
1050 if (pProtect)
1051 pTabProtection.reset(new ScTableProtection(*pProtect));
1052 else
1053 pTabProtection.reset(NULL);
1055 if (IsStreamValid())
1056 SetStreamValid(false);
1059 ScTableProtection* ScTable::GetProtection()
1061 return pTabProtection.get();
1064 Size ScTable::GetPageSize() const
1066 if ( bPageSizeValid )
1067 return aPageSizeTwips;
1068 else
1069 return Size(); // leer
1072 void ScTable::SetRepeatArea( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCROW nEndRow )
1074 // #i117952# page break calculation uses these values (set from ScPrintFunc), not pRepeatColRange/pRepeatRowRange
1075 if ( nStartCol != nRepeatStartX || nEndCol != nRepeatEndX || nStartRow != nRepeatStartY || nEndRow != nRepeatEndY )
1076 InvalidatePageBreaks();
1078 nRepeatStartX = nStartCol;
1079 nRepeatEndX = nEndCol;
1080 nRepeatStartY = nStartRow;
1081 nRepeatEndY = nEndRow;
1084 void ScTable::StartListening( const ScAddress& rAddress, SvtListener* pListener )
1086 if (!ValidCol(rAddress.Col()))
1087 return;
1089 aCol[rAddress.Col()].StartListening( *pListener, rAddress.Row() );
1092 void ScTable::EndListening( const ScAddress& rAddress, SvtListener* pListener )
1094 if (!ValidCol(rAddress.Col()))
1095 return;
1097 aCol[rAddress.Col()].EndListening( *pListener, rAddress.Row() );
1100 void ScTable::StartListening( sc::StartListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener )
1102 if (!ValidCol(nCol))
1103 return;
1105 aCol[nCol].StartListening(rCxt, nRow, rListener);
1108 void ScTable::EndListening( sc::EndListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener )
1110 if (!ValidCol(nCol))
1111 return;
1113 aCol[nCol].EndListening(rCxt, nRow, rListener);
1116 void ScTable::SetPageStyle( const OUString& rName )
1118 if ( aPageStyle != rName )
1120 OUString aStrNew = rName;
1121 SfxStyleSheetBasePool* pStylePool = pDocument->GetStyleSheetPool();
1122 SfxStyleSheetBase* pNewStyle = pStylePool->Find( aStrNew, SFX_STYLE_FAMILY_PAGE );
1124 if ( !pNewStyle )
1126 aStrNew = ScGlobal::GetRscString(STR_STYLENAME_STANDARD);
1127 pNewStyle = pStylePool->Find( aStrNew, SFX_STYLE_FAMILY_PAGE );
1130 if ( aPageStyle != aStrNew )
1132 SfxStyleSheetBase* pOldStyle = pStylePool->Find( aPageStyle, SFX_STYLE_FAMILY_PAGE );
1134 if ( pOldStyle && pNewStyle )
1136 SfxItemSet& rOldSet = pOldStyle->GetItemSet();
1137 SfxItemSet& rNewSet = pNewStyle->GetItemSet();
1138 const sal_uInt16 nOldScale = GET_SCALEVALUE(rOldSet,ATTR_PAGE_SCALE);
1139 const sal_uInt16 nOldScaleToPages = GET_SCALEVALUE(rOldSet,ATTR_PAGE_SCALETOPAGES);
1140 const sal_uInt16 nNewScale = GET_SCALEVALUE(rNewSet,ATTR_PAGE_SCALE);
1141 const sal_uInt16 nNewScaleToPages = GET_SCALEVALUE(rNewSet,ATTR_PAGE_SCALETOPAGES);
1143 if ( (nOldScale != nNewScale) || (nOldScaleToPages != nNewScaleToPages) )
1144 InvalidateTextWidth(NULL, NULL, false, false);
1147 if ( pNewStyle ) // auch ohne den alten (fuer UpdateStdNames)
1148 aPageStyle = aStrNew;
1150 if (IsStreamValid())
1151 SetStreamValid(false);
1156 void ScTable::PageStyleModified( const String& rNewName )
1158 aPageStyle = rNewName;
1159 InvalidateTextWidth(NULL, NULL, false, false); // don't know what was in the style before
1162 void ScTable::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
1163 bool bNumFormatChanged, bool bBroadcast )
1165 if ( pAdrFrom && !pAdrTo )
1167 // Special case: only process the "from" cell.
1168 SCCOL nCol = pAdrFrom->Col();
1169 SCROW nRow = pAdrFrom->Row();
1170 ScColumn& rCol = aCol[nCol];
1171 ScBaseCell* pCell = rCol.GetCell(nRow);
1172 if (!pCell)
1173 return;
1175 rCol.SetTextWidth(nRow, TEXTWIDTH_DIRTY);
1177 if ( bNumFormatChanged )
1178 rCol.SetScriptType(nRow, SC_SCRIPTTYPE_UNKNOWN);
1180 if ( bBroadcast )
1181 { // nur bei CalcAsShown
1182 switch ( pCell->GetCellType() )
1184 case CELLTYPE_VALUE :
1185 pDocument->Broadcast(ScHint(SC_HINT_DATACHANGED, ScAddress(nCol, nRow, nTab)));
1186 break;
1187 case CELLTYPE_FORMULA :
1188 ((ScFormulaCell*)pCell)->SetDirty();
1189 break;
1190 default:
1192 // added to avoid warnings
1197 return;
1200 const SCCOL nCol1 = pAdrFrom ? pAdrFrom->Col() : 0;
1201 const SCROW nRow1 = pAdrFrom ? pAdrFrom->Row() : 0;
1202 const SCCOL nCol2 = pAdrTo ? pAdrTo->Col() : MAXCOL;
1203 const SCROW nRow2 = pAdrTo ? pAdrTo->Row() : MAXROW;
1205 for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
1207 ScColumnTextWidthIterator aIter(aCol[nCol], nRow1, nRow2);
1209 for (; aIter.hasCell(); aIter.next())
1211 SCROW nRow = aIter.getPos();
1212 aIter.setValue(TEXTWIDTH_DIRTY);
1213 ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
1214 if (pCell == 0)
1216 continue;
1219 if ( bNumFormatChanged )
1220 aCol[nCol].SetScriptType(nRow, SC_SCRIPTTYPE_UNKNOWN);
1222 if ( bBroadcast )
1223 { // nur bei CalcAsShown
1224 switch ( pCell->GetCellType() )
1226 case CELLTYPE_VALUE :
1227 pDocument->Broadcast(
1228 ScHint(SC_HINT_DATACHANGED, ScAddress(nCol, nRow, nTab)));
1229 break;
1230 case CELLTYPE_FORMULA :
1231 ((ScFormulaCell*)pCell)->SetDirty();
1232 break;
1233 default:
1235 // added to avoid warnings
1247 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */