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