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