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