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