1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <svx/algitem.hxx>
22 #include <editeng/justifyitem.hxx>
23 #include <unotools/textsearch.hxx>
24 #include <sfx2/objsh.hxx>
27 #include "patattr.hxx"
28 #include "formulacell.hxx"
30 #include "document.hxx"
31 #include "drwlayer.hxx"
32 #include "olinetab.hxx"
33 #include "stlsheet.hxx"
35 #include "globstr.hrc"
36 #include "refupdat.hxx"
37 #include "markdata.hxx"
38 #include "progress.hxx"
40 #include "prnsave.hxx"
41 #include "tabprotection.hxx"
42 #include "sheetevents.hxx"
43 #include "segmenttree.hxx"
45 #include "colorscale.hxx"
46 #include "conditio.hxx"
47 #include "globalnames.hxx"
48 #include "cellvalue.hxx"
49 #include "scmatrix.hxx"
50 #include "refupdatecontext.hxx"
51 #include <rowheightcontext.hxx>
53 #include <formula/vectortoken.hxx>
56 #include <boost/scoped_array.hpp>
62 ScProgress
* GetProgressBar(
63 SCSIZE nCount
, SCSIZE nTotalCount
, ScProgress
* pOuterProgress
, ScDocument
* pDoc
)
65 if (nTotalCount
< 1000)
67 // if the total number of rows is less than 1000, don't even bother
68 // with the progress bar because drawing progress bar can be very
69 // expensive especially in GTK.
74 return pOuterProgress
;
77 return new ScProgress(
78 pDoc
->GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING
), nTotalCount
);
83 void GetOptimalHeightsInColumn(
84 sc::RowHeightContext
& rCxt
, ScColumn
* pCol
, SCROW nStartRow
, SCROW nEndRow
,
85 ScProgress
* pProgress
, sal_uInt32 nProgressStart
)
87 assert(nStartRow
<= nEndRow
);
89 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
91 // first, one time over the whole range
92 // (with the last column in the hope that they most likely still are
93 // on standard format)
95 std::vector
<sal_uInt16
>& rHeights
= rCxt
.getHeightArray();
97 pCol
[MAXCOL
].GetOptimalHeight(rCxt
, nStartRow
, nEndRow
, 0, 0);
99 // from there search for the standard height that is in use in the lower part
101 sal_uInt16 nMinHeight
= rHeights
[nCount
-1];
102 SCSIZE nPos
= nCount
-1;
103 while ( nPos
&& rHeights
[nPos
-1] >= nMinHeight
)
105 SCROW nMinStart
= nStartRow
+ nPos
;
107 sal_uLong nWeightedCount
= 0;
108 for (SCCOL nCol
=0; nCol
<MAXCOL
; nCol
++) // MAXCOL already above
110 pCol
[nCol
].GetOptimalHeight(rCxt
, nStartRow
, nEndRow
, nMinHeight
, nMinStart
);
114 sal_uLong nWeight
= pCol
[nCol
].GetWeightedCount();
115 if (nWeight
) // does not have to be the same Status
117 nWeightedCount
+= nWeight
;
118 pProgress
->SetState( nWeightedCount
+ nProgressStart
);
124 struct OptimalHeightsFuncObjBase
126 virtual ~OptimalHeightsFuncObjBase() {}
127 virtual bool operator() (SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nHeight
) = 0;
130 struct SetRowHeightOnlyFunc
: public OptimalHeightsFuncObjBase
133 SetRowHeightOnlyFunc(ScTable
* pTab
) :
137 virtual bool operator() (SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nHeight
) SAL_OVERRIDE
139 mpTab
->SetRowHeightOnly(nStartRow
, nEndRow
, nHeight
);
144 struct SetRowHeightRangeFunc
: public OptimalHeightsFuncObjBase
150 SetRowHeightRangeFunc(ScTable
* pTab
, double nPPTX
, double nPPTY
) :
156 virtual bool operator() (SCROW nStartRow
, SCROW nEndRow
, sal_uInt16 nHeight
) SAL_OVERRIDE
158 return mpTab
->SetRowHeightRange(nStartRow
, nEndRow
, nHeight
, mnPPTX
, mnPPTY
);
162 bool SetOptimalHeightsToRows(
163 sc::RowHeightContext
& rCxt
,
164 OptimalHeightsFuncObjBase
& rFuncObj
,
165 ScBitMaskCompressedArray
<SCROW
, sal_uInt8
>* pRowFlags
, SCROW nStartRow
, SCROW nEndRow
)
167 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
168 bool bChanged
= false;
171 sal_uInt16 nLast
= 0;
172 for (SCSIZE i
=0; i
<nCount
; i
++)
176 sal_uInt8 nRowFlag
= pRowFlags
->GetValue( nStartRow
+i
, nIndex
, nRegionEndRow
);
177 if ( nRegionEndRow
> nEndRow
)
178 nRegionEndRow
= nEndRow
;
179 SCSIZE nMoreRows
= nRegionEndRow
- ( nStartRow
+i
); // additional equal rows after first
181 bool bAutoSize
= ((nRowFlag
& CR_MANUALSIZE
) == 0);
182 if (bAutoSize
|| rCxt
.isForceAutoSize())
184 if (rCxt
.getExtraHeight())
187 pRowFlags
->SetValue( nStartRow
+i
, nRegionEndRow
, nRowFlag
| CR_MANUALSIZE
);
190 pRowFlags
->SetValue( nStartRow
+i
, nRegionEndRow
, nRowFlag
& ~CR_MANUALSIZE
);
192 for (SCSIZE nInner
= i
; nInner
<= i
+ nMoreRows
; ++nInner
)
196 if (rCxt
.getHeightArray()[nInner
] + rCxt
.getExtraHeight() == nLast
)
197 nRngEnd
= nStartRow
+nInner
;
200 bChanged
|= rFuncObj(nRngStart
, nRngEnd
, nLast
);
206 nLast
= rCxt
.getHeightArray()[nInner
] + rCxt
.getExtraHeight();
207 nRngStart
= nStartRow
+nInner
;
208 nRngEnd
= nStartRow
+nInner
;
215 bChanged
|= rFuncObj(nRngStart
, nRngEnd
, nLast
);
218 i
+= nMoreRows
; // already handled - skip
221 bChanged
|= rFuncObj(nRngStart
, nRngEnd
, nLast
);
228 ScTable::ScTable( ScDocument
* pDoc
, SCTAB nNewTab
, const OUString
& rNewName
,
229 bool bColInfo
, bool bRowInfo
) :
231 aCodeName( rNewName
),
232 nLinkRefreshDelay( 0 ),
234 aPageStyle( ScGlobal::GetRscString(STR_STYLENAME_STANDARD
) ),
235 nRepeatStartX( SCCOL_REPEAT_NONE
),
236 nRepeatEndX( SCCOL_REPEAT_NONE
),
237 nRepeatStartY( SCROW_REPEAT_NONE
),
238 nRepeatEndY( SCROW_REPEAT_NONE
),
239 pTabProtection( NULL
),
241 mpRowHeights( static_cast<ScFlatUInt16RowSegments
*>(NULL
) ),
244 mpHiddenCols(new ScFlatBoolColSegments
),
245 mpHiddenRows(new ScFlatBoolRowSegments
),
246 mpFilteredCols(new ScFlatBoolColSegments
),
247 mpFilteredRows(new ScFlatBoolRowSegments
),
248 pOutlineTable( NULL
),
249 pSheetEvents( NULL
),
254 pSearchText ( NULL
),
255 pSortCollator( NULL
),
256 pRepeatColRange( NULL
),
257 pRepeatRowRange( NULL
),
259 pScenarioRanges( NULL
),
260 aScenarioColor( COL_LIGHTGRAY
),
261 aTabBgColor( COL_AUTO
),
265 mpCondFormatList( new ScConditionalFormatList() ),
269 bPageSizeValid(false),
270 bTableAreaValid(false),
273 bPendingRowHeights(false),
274 bCalcNotification(false),
275 bGlobalKeepQuery(false),
276 bPrintEntireSheet(true),
277 bActiveScenario(false),
278 mbPageBreaksValid(false),
284 pColWidth
= new sal_uInt16
[ MAXCOL
+1 ];
285 pColFlags
= new sal_uInt8
[ MAXCOL
+1 ];
287 for (SCCOL i
=0; i
<=MAXCOL
; i
++)
289 pColWidth
[i
] = STD_COL_WIDTH
;
296 mpRowHeights
.reset(new ScFlatUInt16RowSegments(ScGlobal::nStdRowHeight
));
297 pRowFlags
= new ScBitMaskCompressedArray
< SCROW
, sal_uInt8
>( MAXROW
, 0);
300 if ( pDocument
->IsDocVisible() )
302 // when a sheet is added to a visible document,
303 // initialize its RTL flag from the system locale
304 bLayoutRTL
= ScGlobal::IsSystemRTL();
307 ScDrawLayer
* pDrawLayer
= pDocument
->GetDrawLayer();
310 if ( pDrawLayer
->ScAddPage( nTab
) ) // sal_False (not inserted) during Undo
312 pDrawLayer
->ScRenamePage( nTab
, aName
);
313 sal_uLong nx
= (sal_uLong
) ((double) (MAXCOL
+1) * STD_COL_WIDTH
* HMM_PER_TWIPS
);
314 sal_uLong ny
= (sal_uLong
) ((double) (MAXROW
+1) * ScGlobal::nStdRowHeight
* HMM_PER_TWIPS
);
315 pDrawLayer
->SetPageSize( static_cast<sal_uInt16
>(nTab
), Size( nx
, ny
), false );
319 for (SCCOL k
=0; k
<=MAXCOL
; k
++)
320 aCol
[k
].Init( k
, nTab
, pDocument
);
325 if (!pDocument
->IsInDtorClear())
327 for (SCCOL nCol
= 0; nCol
< MAXCOL
; ++nCol
)
329 aCol
[nCol
].FreeNotes();
331 // In the dtor, don't delete the pages in the wrong order.
332 // (or else nTab does not reflect the page number!)
333 // In ScDocument::Clear is afterwards used from Clear at the Draw Layer to delete everything.
335 ScDrawLayer
* pDrawLayer
= pDocument
->GetDrawLayer();
337 pDrawLayer
->ScRemovePage( nTab
);
344 delete pOutlineTable
;
346 delete pRepeatColRange
;
347 delete pRepeatRowRange
;
348 delete pScenarioRanges
;
350 delete pDBDataNoName
;
351 DestroySortCollator();
353 for (SCCOL k
=0; k
<=MAXCOL
; k
++)
354 aCol
[k
].PrepareBroadcastersForDestruction();
357 void ScTable::GetName( OUString
& rName
) const
362 void ScTable::SetName( const OUString
& rNewName
)
365 aUpperName
.clear(); // invalidated if the name is changed
367 // SetStreamValid is handled in ScDocument::RenameTab
370 const OUString
& ScTable::GetUpperName() const
372 if (aUpperName
.isEmpty() && !aName
.isEmpty())
373 aUpperName
= ScGlobal::pCharClass
->uppercase(aName
);
377 void ScTable::SetVisible( bool bVis
)
379 if (bVisible
!= bVis
&& IsStreamValid())
380 SetStreamValid(false);
385 void ScTable::SetStreamValid( bool bSet
, bool bIgnoreLock
)
387 if ( bIgnoreLock
|| !pDocument
->IsStreamValidLocked() )
391 void ScTable::SetPendingRowHeights( bool bSet
)
393 bPendingRowHeights
= bSet
;
396 void ScTable::SetLayoutRTL( bool bSet
)
401 void ScTable::SetLoadingRTL( bool bSet
)
406 void ScTable::SetTabBgColor(const Color
& rColor
)
408 if (aTabBgColor
!= rColor
)
410 // The tab color has changed. Set this table 'modified'.
411 aTabBgColor
= rColor
;
413 SetStreamValid(false);
417 void ScTable::SetScenario( bool bFlag
)
422 void ScTable::SetLink( sal_uInt8 nMode
,
423 const OUString
& rDoc
, const OUString
& rFlt
, const OUString
& rOpt
,
424 const OUString
& rTab
, sal_uLong nRefreshDelay
)
427 aLinkDoc
= rDoc
; // File
428 aLinkFlt
= rFlt
; // Filter
429 aLinkOpt
= rOpt
; // Filter options
430 aLinkTab
= rTab
; // Sheet name in source file
431 nLinkRefreshDelay
= nRefreshDelay
; // refresh delay in seconds, 0==off
434 SetStreamValid(false);
437 sal_uInt16
ScTable::GetOptimalColWidth( SCCOL nCol
, OutputDevice
* pDev
,
438 double nPPTX
, double nPPTY
,
439 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
440 bool bFormula
, const ScMarkData
* pMarkData
,
441 const ScColWidthParam
* pParam
)
443 return aCol
[nCol
].GetOptimalColWidth( pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
,
444 bFormula
, STD_COL_WIDTH
- STD_EXTRA_WIDTH
, pMarkData
, pParam
);
447 long ScTable::GetNeededSize( SCCOL nCol
, SCROW nRow
,
449 double nPPTX
, double nPPTY
,
450 const Fraction
& rZoomX
, const Fraction
& rZoomY
,
451 bool bWidth
, bool bTotalSize
)
453 ScNeededSizeOptions aOptions
;
454 aOptions
.bSkipMerged
= false; // count merged cells
455 aOptions
.bTotalSize
= bTotalSize
;
457 return aCol
[nCol
].GetNeededSize
458 ( nRow
, pDev
, nPPTX
, nPPTY
, rZoomX
, rZoomY
, bWidth
, aOptions
, NULL
);
461 bool ScTable::SetOptimalHeight(
462 sc::RowHeightContext
& rCxt
, SCROW nStartRow
, SCROW nEndRow
,
463 ScProgress
* pOuterProgress
, sal_uLong nProgressStart
)
465 assert(nStartRow
<= nEndRow
);
467 OSL_ENSURE( rCxt
.getExtraHeight() == 0 || rCxt
.isForceAutoSize(),
468 "automatic OptimalHeight with Extra" );
470 if ( !pDocument
->IsAdjustHeightEnabled() )
475 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
477 ScProgress
* pProgress
= GetProgressBar(nCount
, GetWeightedCount(), pOuterProgress
, pDocument
);
479 rCxt
.getHeightArray().resize(nCount
, 0);
481 GetOptimalHeightsInColumn(rCxt
, aCol
, nStartRow
, nEndRow
, pProgress
, nProgressStart
);
483 SetRowHeightRangeFunc
aFunc(this, rCxt
.getPPTX(), rCxt
.getPPTY());
484 bool bChanged
= SetOptimalHeightsToRows(rCxt
, aFunc
, pRowFlags
, nStartRow
, nEndRow
);
486 if ( pProgress
!= pOuterProgress
)
492 void ScTable::SetOptimalHeightOnly(
493 sc::RowHeightContext
& rCxt
, SCROW nStartRow
, SCROW nEndRow
,
494 ScProgress
* pOuterProgress
, sal_uLong nProgressStart
)
496 OSL_ENSURE( rCxt
.getExtraHeight() == 0 || rCxt
.isForceAutoSize(),
497 "automatic OptimalHeight with Extra" );
499 if ( !pDocument
->IsAdjustHeightEnabled() )
502 SCSIZE nCount
= static_cast<SCSIZE
>(nEndRow
-nStartRow
+1);
504 ScProgress
* pProgress
= GetProgressBar(nCount
, GetWeightedCount(), pOuterProgress
, pDocument
);
506 rCxt
.getHeightArray().resize(nCount
, 0);
508 GetOptimalHeightsInColumn(rCxt
, aCol
, nStartRow
, nEndRow
, pProgress
, nProgressStart
);
510 SetRowHeightOnlyFunc
aFunc(this);
511 SetOptimalHeightsToRows(rCxt
, aFunc
, pRowFlags
, nStartRow
, nEndRow
);
513 if ( pProgress
!= pOuterProgress
)
517 bool ScTable::GetCellArea( SCCOL
& rEndCol
, SCROW
& rEndRow
) const
522 for (SCCOL i
=0; i
<=MAXCOL
; i
++)
524 if (!aCol
[i
].IsEmptyData())
528 SCROW nRow
= aCol
[i
].GetLastDataPos();
532 if ( aCol
[i
].HasCellNotes() )
534 SCROW maxNoteRow
= aCol
[i
].GetCellNotesMaxRow();
535 if (maxNoteRow
>= nMaxY
)
553 bool ScTable::GetTableArea( SCCOL
& rEndCol
, SCROW
& rEndRow
) const
555 bool bRet
= true; //TODO: remember?
556 if (!bTableAreaValid
)
558 bRet
= GetPrintArea(nTableAreaX
, nTableAreaY
, true);
559 bTableAreaValid
= true;
561 rEndCol
= nTableAreaX
;
562 rEndRow
= nTableAreaY
;
566 const SCCOL SC_COLUMNS_STOP
= 30;
568 bool ScTable::GetPrintArea( SCCOL
& rEndCol
, SCROW
& rEndRow
, bool bNotes
, bool bFullFormattedArea
) const
575 for (i
=0; i
<=MAXCOL
; i
++) // Test data
577 if (!aCol
[i
].IsEmptyData())
582 SCROW nColY
= aCol
[i
].GetLastDataPos();
588 if ( aCol
[i
].HasCellNotes() )
590 SCROW maxNoteRow
= aCol
[i
].GetCellNotesMaxRow();
591 if (maxNoteRow
>= nMaxY
)
605 SCCOL nMaxDataX
= nMaxX
;
607 for (i
=0; i
<=MAXCOL
; i
++) // Test attribute
610 if (aCol
[i
].GetLastVisibleAttr( nLastRow
, bFullFormattedArea
))
614 if (nLastRow
> nMaxY
)
619 if (nMaxX
== MAXCOL
) // omit attribute at the right
622 while ( nMaxX
>0 && aCol
[nMaxX
].IsVisibleAttrEqual(aCol
[nMaxX
+1]) )
626 if ( nMaxX
< nMaxDataX
)
630 else if ( nMaxX
> nMaxDataX
)
632 SCCOL nAttrStartX
= nMaxDataX
+ 1;
633 while ( nAttrStartX
< MAXCOL
)
635 SCCOL nAttrEndX
= nAttrStartX
;
636 while ( nAttrEndX
< MAXCOL
&& aCol
[nAttrStartX
].IsVisibleAttrEqual(aCol
[nAttrEndX
+1]) )
638 if ( nAttrEndX
+ 1 - nAttrStartX
>= SC_COLUMNS_STOP
)
640 // found equally-formatted columns behind data -> stop before these columns
641 nMaxX
= nAttrStartX
- 1;
643 // also don't include default-formatted columns before that
645 while ( nMaxX
> nMaxDataX
&& !aCol
[nMaxX
].GetLastVisibleAttr( nDummyRow
) )
649 nAttrStartX
= nAttrEndX
+ 1;
658 bool ScTable::GetPrintAreaHor( SCROW nStartRow
, SCROW nEndRow
,
659 SCCOL
& rEndCol
, bool /* bNotes */ ) const
665 for (i
=0; i
<=MAXCOL
; i
++) // Test attribute
667 if (aCol
[i
].HasVisibleAttrIn( nStartRow
, nEndRow
))
674 if (nMaxX
== MAXCOL
) // omit attribute at the right
677 while ( nMaxX
>0 && aCol
[nMaxX
].IsVisibleAttrEqual(aCol
[nMaxX
+1], nStartRow
, nEndRow
) )
681 for (i
=0; i
<=MAXCOL
; i
++) // Daten testen
683 if (!aCol
[i
].IsEmptyBlock( nStartRow
, nEndRow
)) //TODO: bNotes ??????
695 bool ScTable::GetPrintAreaVer( SCCOL nStartCol
, SCCOL nEndCol
,
696 SCROW
& rEndRow
, bool bNotes
) const
702 for (i
=nStartCol
; i
<=nEndCol
; i
++) // Test attribute
705 if (aCol
[i
].GetLastVisibleAttr( nLastRow
))
708 if (nLastRow
> nMaxY
)
713 for (i
=nStartCol
; i
<=nEndCol
; i
++) // Test data
715 if (!aCol
[i
].IsEmptyData())
718 SCROW nColY
= aCol
[i
].GetLastDataPos();
724 if ( aCol
[i
].HasCellNotes() )
726 SCROW maxNoteRow
=aCol
[i
].GetCellNotesMaxRow();
727 if (maxNoteRow
> nMaxY
)
740 bool ScTable::GetDataStart( SCCOL
& rStartCol
, SCROW
& rStartRow
) const
743 SCCOL nMinX
= MAXCOL
;
744 SCROW nMinY
= MAXROW
;
747 for (i
=0; i
<=MAXCOL
; i
++) // Test attribute
750 if (aCol
[i
].GetFirstVisibleAttr( nFirstRow
))
755 if (nFirstRow
< nMinY
)
760 if (nMinX
== 0) // omit attribute at the right
762 if ( aCol
[0].IsVisibleAttrEqual(aCol
[1]) ) // no single ones
765 while ( nMinX
<MAXCOL
&& aCol
[nMinX
].IsVisibleAttrEqual(aCol
[nMinX
-1]) )
770 bool bDatFound
= false;
771 for (i
=0; i
<=MAXCOL
; i
++) // Test data
773 if (!aCol
[i
].IsEmptyData())
775 if (!bDatFound
&& i
<nMinX
)
777 bFound
= bDatFound
= true;
778 SCROW nRow
= aCol
[i
].GetFirstDataPos();
782 if ( aCol
[i
].HasCellNotes() )
784 SCROW minNoteRow
= aCol
[i
].GetCellNotesMinRow();
785 if (minNoteRow
<= nMinY
)
802 void ScTable::GetDataArea( SCCOL
& rStartCol
, SCROW
& rStartRow
, SCCOL
& rEndCol
, SCROW
& rEndRow
,
803 bool bIncludeOld
, bool bOnlyDown
) const
805 // return the smallest area containing at least all contiguous cells having data. This area
806 // is a square containing also empty cells. It may shrink or extend the area given as input
807 // Flags as modifiers:
809 // bIncludeOld = true ensure that the returned area contains at least the initial area,
810 // independently of the emptniess of rows / columns (i.e. does not allow shrinking)
811 // bOnlyDown = true means extend / shrink the inputed area only down, i.e modifiy only rEndRow
816 bool bBottom
= false;
817 bool bChanged
= false;
825 SCROW nStart
= rStartRow
;
826 SCROW nEnd
= rEndRow
;
827 if (nStart
>0) --nStart
;
828 if (nEnd
<MAXROW
) ++nEnd
;
830 if (rEndCol
< MAXCOL
)
831 if (!aCol
[rEndCol
+1].IsEmptyBlock(nStart
,nEnd
))
839 if (!aCol
[rStartCol
-1].IsEmptyBlock(nStart
,nEnd
))
848 SCROW nTest
= rStartRow
-1;
849 bool needExtend
= false;
850 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& !needExtend
; i
++)
851 if (aCol
[i
].HasDataAt(nTest
))
862 if (rEndRow
< MAXROW
)
864 SCROW nTest
= rEndRow
+1;
865 bool needExtend
= false;
866 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& !needExtend
; i
++)
867 if (aCol
[i
].HasDataAt(nTest
))
879 if ( !bIncludeOld
&& !bOnlyDown
)
882 while ( aCol
[rStartCol
].IsEmptyBlock(rStartRow
,rEndRow
) && rStartCol
< MAXCOL
&& rStartCol
< rEndCol
)
886 while ( aCol
[rEndCol
].IsEmptyBlock(rStartRow
,rEndRow
) && rEndCol
> 0 && rStartCol
< rEndCol
)
889 if ( !bTop
&& rStartRow
< MAXROW
&& rStartRow
< rEndRow
)
894 for ( SCCOL i
= rStartCol
; i
<=rEndCol
&& bShrink
; i
++)
895 if (aCol
[i
].HasDataAt(rStartRow
))
899 } while (bShrink
&& rStartRow
< MAXROW
&& rStartRow
< rEndRow
);
905 if ( !bBottom
&& rEndRow
> 0 && rStartRow
< rEndRow
)
907 SCROW nLastDataRow
= GetLastDataRow( rStartCol
, rEndCol
, rEndRow
);
908 if (nLastDataRow
< rEndRow
)
909 rEndRow
= std::max( rStartRow
, nLastDataRow
);
914 bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk
, SCCOL
& rStartCol
, SCROW
& rStartRow
,
915 SCCOL
& rEndCol
, SCROW
& rEndRow
, bool bColumnsOnly
, bool bStickyTopRow
, bool bStickyLeftCol
) const
919 PutInOrder( rStartCol
, rEndCol
);
920 PutInOrder( rStartRow
, rEndRow
);
922 rStartCol
= 0, o_bShrunk
= true;
924 rStartRow
= 0, o_bShrunk
= true;
925 if (rEndCol
> MAXCOL
)
926 rEndCol
= MAXCOL
, o_bShrunk
= true;
927 if (rEndRow
> MAXROW
)
928 rEndRow
= MAXROW
, o_bShrunk
= true;
930 while (rStartCol
< rEndCol
)
932 if (aCol
[rEndCol
].IsEmptyBlock( rStartRow
, rEndRow
))
943 while (rStartCol
< rEndCol
)
945 if (aCol
[rStartCol
].IsEmptyBlock( rStartRow
, rEndRow
))
959 while (rStartRow
< rEndRow
)
962 for (SCCOL i
=rStartCol
; i
<=rEndCol
&& !bFound
; i
++)
964 if (aCol
[i
].HasDataAt( rStartRow
))
977 while (rStartRow
< rEndRow
)
979 SCROW nLastDataRow
= GetLastDataRow( rStartCol
, rEndCol
, rEndRow
);
980 if (0 <= nLastDataRow
&& nLastDataRow
< rEndRow
)
982 rEndRow
= std::max( rStartRow
, nLastDataRow
);
990 return rStartCol
!= rEndCol
|| (bColumnsOnly
?
991 !aCol
[rStartCol
].IsEmptyBlock( rStartRow
, rEndRow
) :
992 (rStartRow
!= rEndRow
|| aCol
[rStartCol
].HasDataAt( rStartRow
)));
995 SCROW
ScTable::GetLastDataRow( SCCOL nCol1
, SCCOL nCol2
, SCROW nLastRow
) const
997 if (!ValidCol(nCol1
) || !ValidCol(nCol2
))
1000 SCROW nNewLastRow
= 0;
1001 for (SCCOL i
= nCol1
; i
<= nCol2
; ++i
)
1003 SCROW nThis
= aCol
[i
].GetLastDataPos(nLastRow
);
1004 if (nNewLastRow
< nThis
)
1005 nNewLastRow
= nThis
;
1011 SCSIZE
ScTable::GetEmptyLinesInBlock( SCCOL nStartCol
, SCROW nStartRow
,
1012 SCCOL nEndCol
, SCROW nEndRow
, ScDirection eDir
) const
1016 if ((eDir
== DIR_BOTTOM
) || (eDir
== DIR_TOP
))
1018 nCount
= static_cast<SCSIZE
>(nEndRow
- nStartRow
+ 1);
1019 for (nCol
= nStartCol
; nCol
<= nEndCol
; nCol
++)
1020 nCount
= std::min(nCount
, aCol
[nCol
].GetEmptyLinesInBlock(nStartRow
, nEndRow
, eDir
));
1022 else if (eDir
== DIR_RIGHT
)
1025 while (((SCsCOL
)nCol
>= (SCsCOL
)nStartCol
) &&
1026 aCol
[nCol
].IsEmptyBlock(nStartRow
, nEndRow
))
1035 while ((nCol
<= nEndCol
) && aCol
[nCol
].IsEmptyBlock(nStartRow
, nEndRow
))
1044 bool ScTable::IsEmptyLine( SCROW nRow
, SCCOL nStartCol
, SCCOL nEndCol
) const
1046 bool bFound
= false;
1047 for (SCCOL i
=nStartCol
; i
<=nEndCol
&& !bFound
; i
++)
1048 if (aCol
[i
].HasDataAt(nRow
))
1053 void ScTable::LimitChartArea( SCCOL
& rStartCol
, SCROW
& rStartRow
, SCCOL
& rEndCol
, SCROW
& rEndRow
) const
1055 while ( rStartCol
<rEndCol
&& aCol
[rStartCol
].IsEmptyBlock(rStartRow
,rEndRow
) )
1058 while ( rStartCol
<rEndCol
&& aCol
[rEndCol
].IsEmptyBlock(rStartRow
,rEndRow
) )
1061 while ( rStartRow
<rEndRow
&& IsEmptyLine(rStartRow
, rStartCol
, rEndCol
) )
1064 while ( rStartRow
<rEndRow
&& IsEmptyLine(rEndRow
, rStartCol
, rEndCol
) )
1068 SCCOL
ScTable::FindNextVisibleCol( SCCOL nCol
, bool bRight
) const
1074 bool bHidden
= pDocument
->ColHidden(nCol
, nTab
, NULL
, &nEnd
);
1078 return std::min
<SCCOL
>(MAXCOL
, nCol
);
1083 SCCOL nStart
= MAXCOL
;
1084 bool bHidden
= pDocument
->ColHidden(nCol
, nTab
, &nStart
, NULL
);
1088 return std::max
<SCCOL
>(0, nCol
);
1092 SCCOL
ScTable::FindNextVisibleColWithContent( SCCOL nCol
, bool bRight
, SCROW nRow
) const
1103 bool bHidden
= pDocument
->ColHidden( nCol
, nTab
, NULL
, &nEndCol
);
1107 if(nEndCol
>= MAXCOL
)
1111 if(aCol
[nCol
].HasVisibleDataAt(nRow
))
1114 while(nCol
< MAXCOL
);
1126 SCCOL nStartCol
= MAXCOL
;
1127 bool bHidden
= pDocument
->ColHidden( nCol
, nTab
, &nStartCol
, NULL
);
1130 nCol
= nStartCol
-1;
1135 if(aCol
[nCol
].HasVisibleDataAt(nRow
))
1144 void ScTable::FindAreaPos( SCCOL
& rCol
, SCROW
& rRow
, ScMoveDirection eDirection
) const
1146 if (eDirection
== SC_MOVE_LEFT
|| eDirection
== SC_MOVE_RIGHT
)
1148 SCCOL nNewCol
= rCol
;
1149 bool bThere
= aCol
[nNewCol
].HasVisibleDataAt(rRow
);
1150 bool bRight
= (eDirection
== SC_MOVE_RIGHT
);
1153 if(nNewCol
>= MAXCOL
&& eDirection
== SC_MOVE_RIGHT
)
1155 else if(nNewCol
== 0 && eDirection
== SC_MOVE_LEFT
)
1158 SCCOL nNextCol
= FindNextVisibleCol( nNewCol
, bRight
);
1160 if(aCol
[nNextCol
].HasVisibleDataAt(rRow
))
1162 bool bFound
= false;
1166 nNextCol
= FindNextVisibleCol( nNewCol
, bRight
);
1167 if(aCol
[nNextCol
].HasVisibleDataAt(rRow
))
1172 while(!bFound
&& nNextCol
> 0 && nNextCol
< MAXCOL
);
1176 nNewCol
= FindNextVisibleColWithContent(nNewCol
, bRight
, rRow
);
1181 nNewCol
= FindNextVisibleColWithContent(nNewCol
, bRight
, rRow
);
1192 aCol
[rCol
].FindDataAreaPos(rRow
,eDirection
== SC_MOVE_DOWN
);
1196 bool ScTable::ValidNextPos( SCCOL nCol
, SCROW nRow
, const ScMarkData
& rMark
,
1197 bool bMarked
, bool bUnprotected
) const
1199 if (!ValidCol(nCol
) || !ValidRow(nRow
))
1202 if (pDocument
->HasAttrib(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_OVERLAPPED
))
1203 // Skip an overlapped cell.
1206 if (bMarked
&& !rMark
.IsCellMarked(nCol
,nRow
))
1209 if (bUnprotected
&& static_cast<const ScProtectionAttr
*>(
1210 GetAttr(nCol
,nRow
,ATTR_PROTECTION
))->GetProtection())
1213 if (bMarked
|| bUnprotected
) //TODO: also in other case ???
1215 // Hidden cells must be skipped, as the cursor would end up on the next cell
1216 // even if it is protected or not marked.
1217 //TODO: control per Extra-Parameter, only for Cursor movement ???
1219 if (RowHidden(nRow
))
1222 if (ColHidden(nCol
))
1229 void ScTable::GetNextPos( SCCOL
& rCol
, SCROW
& rRow
, SCsCOL nMovX
, SCsROW nMovY
,
1230 bool bMarked
, bool bUnprotected
, const ScMarkData
& rMark
) const
1232 if (bUnprotected
&& !IsProtected()) // Is sheet really protected?
1233 bUnprotected
= false;
1235 sal_uInt16 nWrap
= 0;
1239 nCol
= sal::static_int_cast
<SCsCOL
>( nCol
+ nMovX
);
1240 nRow
= sal::static_int_cast
<SCsROW
>( nRow
+ nMovY
);
1242 OSL_ENSURE( !nMovY
|| !bUnprotected
,
1243 "GetNextPos with bUnprotected horizontal not implemented" );
1245 if ( nMovY
&& bMarked
)
1247 bool bUp
= ( nMovY
< 0 );
1248 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1249 while ( ValidRow(nRow
) &&
1250 (RowHidden(nRow
) || pDocument
->HasAttrib(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_OVERLAPPED
)) )
1252 // skip hidden rows (see above)
1254 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1257 while ( nRow
< 0 || nRow
> MAXROW
)
1259 nCol
= sal::static_int_cast
<SCsCOL
>( nCol
+ static_cast<SCsCOL
>(nMovY
) );
1260 while ( ValidCol(nCol
) && ColHidden(nCol
) )
1261 nCol
= sal::static_int_cast
<SCsCOL
>( nCol
+ static_cast<SCsCOL
>(nMovY
) ); // skip hidden rows (see above)
1268 else if (nCol
> MAXCOL
)
1276 else if (nRow
> MAXROW
)
1278 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1279 while ( ValidRow(nRow
) &&
1280 (RowHidden(nRow
) || pDocument
->HasAttrib(nCol
, nRow
, nTab
, nCol
, nRow
, nTab
, HASATTR_OVERLAPPED
)) )
1282 // skip hidden rows (see above)
1284 nRow
= rMark
.GetNextMarked( nCol
, nRow
, bUp
);
1289 if ( nMovX
&& ( bMarked
|| bUnprotected
) )
1291 // wrap initial skip counting:
1307 if ( !ValidNextPos(nCol
, nRow
, rMark
, bMarked
, bUnprotected
) )
1309 boost::scoped_array
<SCsROW
> pNextRows(new SCsROW
[MAXCOL
+1]);
1312 if ( nMovX
> 0 ) // forward
1314 for (i
=0; i
<=MAXCOL
; i
++)
1315 pNextRows
[i
] = (i
<nCol
) ? (nRow
+1) : nRow
;
1318 SCsROW nNextRow
= pNextRows
[nCol
] + 1;
1320 nNextRow
= rMark
.GetNextMarked( nCol
, nNextRow
, false );
1322 nNextRow
= aCol
[nCol
].GetNextUnprotected( nNextRow
, false );
1323 pNextRows
[nCol
] = nNextRow
;
1325 SCsROW nMinRow
= MAXROW
+1;
1326 for (i
=0; i
<=MAXCOL
; i
++)
1327 if (pNextRows
[i
] < nMinRow
) // when two equal on the left
1329 nMinRow
= pNextRows
[i
];
1334 if ( nRow
> MAXROW
)
1336 if (++nWrap
>= 2) break; // handle invalid value
1339 for (i
=0; i
<=MAXCOL
; i
++)
1340 pNextRows
[i
] = 0; // do it all over again
1343 while ( !ValidNextPos(nCol
, nRow
, rMark
, bMarked
, bUnprotected
) );
1347 for (i
=0; i
<=MAXCOL
; i
++)
1348 pNextRows
[i
] = (i
>nCol
) ? (nRow
-1) : nRow
;
1351 SCsROW nNextRow
= pNextRows
[nCol
] - 1;
1353 nNextRow
= rMark
.GetNextMarked( nCol
, nNextRow
, true );
1355 nNextRow
= aCol
[nCol
].GetNextUnprotected( nNextRow
, true );
1356 pNextRows
[nCol
] = nNextRow
;
1358 SCsROW nMaxRow
= -1;
1359 for (i
=0; i
<=MAXCOL
; i
++)
1360 if (pNextRows
[i
] >= nMaxRow
) // when two equal on the right
1362 nMaxRow
= pNextRows
[i
];
1369 if (++nWrap
>= 2) break; // handle invalid value
1372 for (i
=0; i
<=MAXCOL
; i
++)
1373 pNextRows
[i
] = MAXROW
; // do it all over again
1376 while ( !ValidNextPos(nCol
, nRow
, rMark
, bMarked
, bUnprotected
) );
1381 // Invalid values show up for instane for Tab, when nothing is selected and not
1382 // protected (left / right edge), then leave values unchanged.
1384 if (ValidColRow(nCol
,nRow
))
1391 bool ScTable::GetNextMarkedCell( SCCOL
& rCol
, SCROW
& rRow
, const ScMarkData
& rMark
) const
1393 const ScMarkArray
* pMarkArray
= rMark
.GetArray();
1394 OSL_ENSURE(pMarkArray
,"GetNextMarkedCell without MarkArray");
1400 while ( rCol
<= MAXCOL
)
1402 const ScMarkArray
& rArray
= pMarkArray
[rCol
];
1403 while ( rRow
<= MAXROW
)
1405 SCROW nStart
= (SCROW
) rArray
.GetNextMarked( (SCsROW
) rRow
, false );
1406 if ( nStart
<= MAXROW
)
1408 SCROW nEnd
= rArray
.GetMarkEnd( nStart
, false );
1410 const sc::CellStoreType
& rCells
= aCol
[rCol
].maCells
;
1411 std::pair
<sc::CellStoreType::const_iterator
,size_t> aPos
= rCells
.position(nStart
);
1412 sc::CellStoreType::const_iterator it
= aPos
.first
;
1413 SCROW nTestRow
= nStart
;
1414 if (it
->type
== sc::element_type_empty
)
1416 // Skip the empty block.
1417 nTestRow
+= it
->size
- aPos
.second
;
1419 if (it
== rCells
.end())
1427 if (nTestRow
<= nEnd
)
1434 rRow
= nEnd
+ 1; // Search for next selected range
1437 rRow
= MAXROW
+ 1; // End of column
1440 ++rCol
; // test next column
1443 return false; // Through all columns
1446 void ScTable::UpdateDrawRef( UpdateRefMode eUpdateRefMode
, SCCOL nCol1
, SCROW nRow1
, SCTAB nTab1
,
1447 SCCOL nCol2
, SCROW nRow2
, SCTAB nTab2
,
1448 SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
, bool bUpdateNoteCaptionPos
)
1450 if ( nTab
>= nTab1
&& nTab
<= nTab2
&& nDz
== 0 ) // only within the table
1452 ScDrawLayer
* pDrawLayer
= pDocument
->GetDrawLayer();
1453 if ( eUpdateRefMode
!= URM_COPY
&& pDrawLayer
)
1455 if ( eUpdateRefMode
== URM_MOVE
)
1457 nCol1
= sal::static_int_cast
<SCCOL
>( nCol1
- nDx
);
1458 nRow1
= sal::static_int_cast
<SCROW
>( nRow1
- nDy
);
1459 nCol2
= sal::static_int_cast
<SCCOL
>( nCol2
- nDx
);
1460 nRow2
= sal::static_int_cast
<SCROW
>( nRow2
- nDy
);
1462 pDrawLayer
->MoveArea( nTab
, nCol1
,nRow1
, nCol2
,nRow2
, nDx
,nDy
,
1463 (eUpdateRefMode
== URM_INSDEL
), bUpdateNoteCaptionPos
);
1468 void ScTable::UpdateReference(
1469 sc::RefUpdateContext
& rCxt
, ScDocument
* pUndoDoc
, bool bIncludeDraw
, bool bUpdateNoteCaptionPos
)
1471 bool bUpdated
= false;
1474 if (rCxt
.meMode
== URM_COPY
)
1476 i
= rCxt
.maRange
.aStart
.Col();
1477 iMax
= rCxt
.maRange
.aEnd
.Col();
1485 UpdateRefMode eUpdateRefMode
= rCxt
.meMode
;
1486 SCCOL nDx
= rCxt
.mnColDelta
;
1487 SCROW nDy
= rCxt
.mnRowDelta
;
1488 SCTAB nDz
= rCxt
.mnTabDelta
;
1489 SCCOL nCol1
= rCxt
.maRange
.aStart
.Col(), nCol2
= rCxt
.maRange
.aEnd
.Col();
1490 SCROW nRow1
= rCxt
.maRange
.aStart
.Row(), nRow2
= rCxt
.maRange
.aEnd
.Row();
1491 SCTAB nTab1
= rCxt
.maRange
.aStart
.Tab(), nTab2
= rCxt
.maRange
.aEnd
.Tab();
1493 // Named expressions need to be updated before formulas acessing them.
1495 mpRangeName
->UpdateReference(rCxt
, nTab
);
1497 for ( ; i
<=iMax
; i
++)
1498 bUpdated
|= aCol
[i
].UpdateReference(rCxt
, pUndoDoc
);
1501 UpdateDrawRef( eUpdateRefMode
, nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
, nDx
, nDy
, nDz
, bUpdateNoteCaptionPos
);
1503 if ( nTab
>= nTab1
&& nTab
<= nTab2
&& nDz
== 0 ) // print ranges: only within the table
1511 bool bRecalcPages
= false;
1513 for ( ScRangeVec::iterator aIt
= aPrintRanges
.begin(), aEnd
= aPrintRanges
.end(); aIt
!= aEnd
; ++aIt
)
1515 nSCol
= aIt
->aStart
.Col();
1516 nSRow
= aIt
->aStart
.Row();
1517 nECol
= aIt
->aEnd
.Col();
1518 nERow
= aIt
->aEnd
.Row();
1520 // do not try to modify sheet index of print range
1521 if ( ScRefUpdate::Update( pDocument
, eUpdateRefMode
,
1522 nCol1
,nRow1
,nTab
, nCol2
,nRow2
,nTab
,
1524 nSCol
,nSRow
,nSTab
, nECol
,nERow
,nETab
) )
1526 *aIt
= ScRange( nSCol
, nSRow
, 0, nECol
, nERow
, 0 );
1527 bRecalcPages
= true;
1531 if ( pRepeatColRange
)
1533 nSCol
= pRepeatColRange
->aStart
.Col();
1534 nSRow
= pRepeatColRange
->aStart
.Row();
1535 nECol
= pRepeatColRange
->aEnd
.Col();
1536 nERow
= pRepeatColRange
->aEnd
.Row();
1538 // do not try to modify sheet index of repeat range
1539 if ( ScRefUpdate::Update( pDocument
, eUpdateRefMode
,
1540 nCol1
,nRow1
,nTab
, nCol2
,nRow2
,nTab
,
1542 nSCol
,nSRow
,nSTab
, nECol
,nERow
,nETab
) )
1544 *pRepeatColRange
= ScRange( nSCol
, nSRow
, 0, nECol
, nERow
, 0 );
1545 bRecalcPages
= true;
1546 nRepeatStartX
= nSCol
; // for UpdatePageBreaks
1547 nRepeatEndX
= nECol
;
1551 if ( pRepeatRowRange
)
1553 nSCol
= pRepeatRowRange
->aStart
.Col();
1554 nSRow
= pRepeatRowRange
->aStart
.Row();
1555 nECol
= pRepeatRowRange
->aEnd
.Col();
1556 nERow
= pRepeatRowRange
->aEnd
.Row();
1558 // do not try to modify sheet index of repeat range
1559 if ( ScRefUpdate::Update( pDocument
, eUpdateRefMode
,
1560 nCol1
,nRow1
,nTab
, nCol2
,nRow2
,nTab
,
1562 nSCol
,nSRow
,nSTab
, nECol
,nERow
,nETab
) )
1564 *pRepeatRowRange
= ScRange( nSCol
, nSRow
, 0, nECol
, nERow
, 0 );
1565 bRecalcPages
= true;
1566 nRepeatStartY
= nSRow
; // for UpdatePageBreaks
1567 nRepeatEndY
= nERow
;
1571 // updating print ranges is not necessary with multiple print ranges
1572 if ( bRecalcPages
&& GetPrintRangeCount() <= 1 )
1574 UpdatePageBreaks(NULL
);
1576 pDocument
->RepaintRange( ScRange(0,0,nTab
,MAXCOL
,MAXROW
,nTab
) );
1580 if (bUpdated
&& IsStreamValid())
1581 SetStreamValid(false);
1583 if(mpCondFormatList
)
1584 mpCondFormatList
->UpdateReference(rCxt
);
1587 pTabProtection
->updateReference( eUpdateRefMode
, pDocument
, rCxt
.maRange
, nDx
, nDy
, nDz
);
1590 void ScTable::UpdateTranspose( const ScRange
& rSource
, const ScAddress
& rDest
,
1591 ScDocument
* pUndoDoc
)
1593 for ( SCCOL i
=0; i
<=MAXCOL
; i
++ )
1594 aCol
[i
].UpdateTranspose( rSource
, rDest
, pUndoDoc
);
1597 void ScTable::UpdateGrow( const ScRange
& rArea
, SCCOL nGrowX
, SCROW nGrowY
)
1599 for ( SCCOL i
=0; i
<=MAXCOL
; i
++ )
1600 aCol
[i
].UpdateGrow( rArea
, nGrowX
, nGrowY
);
1603 void ScTable::UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
)
1605 // Store the old tab number in sc::UpdatedRangeNames for
1606 // ScTokenArray::AdjustReferenceOnInsertedTab() to check with
1609 mpRangeName
->UpdateInsertTab(rCxt
, nTab
);
1611 if (nTab
>= rCxt
.mnInsertPos
)
1613 nTab
+= rCxt
.mnSheets
;
1615 pDBDataNoName
->UpdateMoveTab(nTab
- 1 ,nTab
);
1618 if (mpCondFormatList
)
1619 mpCondFormatList
->UpdateInsertTab(rCxt
);
1622 pTabProtection
->updateReference( URM_INSDEL
, pDocument
,
1623 ScRange( 0, 0, rCxt
.mnInsertPos
, MAXCOL
, MAXROW
, MAXTAB
),
1624 0, 0, rCxt
.mnSheets
);
1626 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
1627 aCol
[i
].UpdateInsertTab(rCxt
);
1629 if (IsStreamValid())
1630 SetStreamValid(false);
1633 void ScTable::UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
)
1635 // Store the old tab number in sc::UpdatedRangeNames for
1636 // ScTokenArray::AdjustReferenceOnDeletedTab() to check with
1639 mpRangeName
->UpdateDeleteTab(rCxt
, nTab
);
1641 if (nTab
> rCxt
.mnDeletePos
)
1643 nTab
-= rCxt
.mnSheets
;
1645 pDBDataNoName
->UpdateMoveTab(nTab
+ 1,nTab
);
1648 if (mpCondFormatList
)
1649 mpCondFormatList
->UpdateDeleteTab(rCxt
);
1652 pTabProtection
->updateReference( URM_INSDEL
, pDocument
,
1653 ScRange( 0, 0, rCxt
.mnDeletePos
, MAXCOL
, MAXROW
, MAXTAB
),
1654 0, 0, -rCxt
.mnSheets
);
1656 for (SCCOL i
= 0; i
<= MAXCOL
; ++i
)
1657 aCol
[i
].UpdateDeleteTab(rCxt
);
1659 if (IsStreamValid())
1660 SetStreamValid(false);
1663 void ScTable::UpdateMoveTab(
1664 sc::RefUpdateMoveTabContext
& rCxt
, SCTAB nTabNo
, ScProgress
* pProgress
)
1668 mpRangeName
->UpdateMoveTab(rCxt
, nTab
);
1671 pDBDataNoName
->UpdateMoveTab(rCxt
.mnOldPos
, rCxt
.mnNewPos
);
1673 if(mpCondFormatList
)
1674 mpCondFormatList
->UpdateMoveTab(rCxt
);
1677 pTabProtection
->updateReference( URM_REORDER
, pDocument
,
1678 ScRange( 0, 0, rCxt
.mnOldPos
, MAXCOL
, MAXROW
, MAXTAB
),
1679 0, 0, rCxt
.mnNewPos
- rCxt
.mnOldPos
);
1681 for ( SCCOL i
=0; i
<= MAXCOL
; i
++ )
1683 aCol
[i
].UpdateMoveTab(rCxt
, nTabNo
);
1685 pProgress
->SetState(pProgress
->GetState() + aCol
[i
].GetCodeCount());
1688 if (IsStreamValid())
1689 SetStreamValid(false);
1692 void ScTable::UpdateCompile( bool bForceIfNameInUse
)
1694 for (SCCOL i
=0; i
<= MAXCOL
; i
++)
1696 aCol
[i
].UpdateCompile( bForceIfNameInUse
);
1700 void ScTable::SetTabNo(SCTAB nNewTab
)
1703 for (SCCOL i
=0; i
<= MAXCOL
; i
++) aCol
[i
].SetTabNo(nNewTab
);
1706 void ScTable::FindRangeNamesInUse(SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
,
1707 std::set
<sal_uInt16
>& rIndexes
) const
1709 for (SCCOL i
= nCol1
; i
<= nCol2
&& ValidCol(i
); i
++)
1710 aCol
[i
].FindRangeNamesInUse(nRow1
, nRow2
, rIndexes
);
1713 void ScTable::ExtendPrintArea( OutputDevice
* pDev
,
1714 SCCOL
/* nStartCol */, SCROW nStartRow
, SCCOL
& rEndCol
, SCROW nEndRow
)
1716 if ( !pColFlags
|| !pRowFlags
)
1718 OSL_FAIL("ExtendPrintArea: No ColInfo or RowInfo");
1722 Point aPix1000
= pDev
->LogicToPixel( Point(1000,1000), MAP_TWIP
);
1723 double nPPTX
= aPix1000
.X() / 1000.0;
1724 double nPPTY
= aPix1000
.Y() / 1000.0;
1726 // First, mark those columns that we need to skip i.e. hidden and empty columns.
1728 ScFlatBoolColSegments aSkipCols
;
1729 aSkipCols
.setFalse(0, MAXCOL
);
1730 for (SCCOL i
= 0; i
<= MAXCOL
; ++i
)
1733 if (ColHidden(i
, NULL
, &nLastCol
))
1735 // Columns are hidden in this range.
1736 aSkipCols
.setTrue(i
, nLastCol
);
1740 // These columns are visible. Check for empty columns.
1741 for (SCCOL j
= i
; j
<= nLastCol
; ++j
)
1743 if (aCol
[j
].GetCellCount() == 0)
1745 aSkipCols
.setTrue(j
,j
);
1751 ScFlatBoolColSegments::RangeData aColData
;
1752 for (SCCOL nCol
= rEndCol
; nCol
>= 0; --nCol
)
1754 if (!aSkipCols
.getRangeData(nCol
, aColData
))
1755 // Failed to get the data. This should never happen!
1758 if (aColData
.mbValue
)
1760 // Skip these columns.
1761 nCol
= aColData
.mnCol1
; // move toward 0.
1765 // These are visible and non-empty columns.
1766 for (SCCOL nDataCol
= nCol
; 0 <= nDataCol
&& nDataCol
>= aColData
.mnCol1
; --nDataCol
)
1768 SCCOL nPrintCol
= nDataCol
;
1769 VisibleDataCellIterator
aIter(*mpHiddenRows
, aCol
[nDataCol
]);
1770 ScRefCellValue aCell
= aIter
.reset(nStartRow
);
1771 if (aCell
.isEmpty())
1772 // No visible cells found in this column. Skip it.
1775 while (!aCell
.isEmpty())
1777 SCCOL nNewCol
= nDataCol
;
1778 SCROW nRow
= aIter
.getRow();
1780 // Went past the last row position. Bail out.
1783 MaybeAddExtraColumn(nNewCol
, nRow
, pDev
, nPPTX
, nPPTY
);
1784 if (nNewCol
> nPrintCol
)
1785 nPrintCol
= nNewCol
;
1786 aCell
= aIter
.next();
1789 if (nPrintCol
> rEndCol
)
1790 // Make sure we don't shrink the print area.
1791 rEndCol
= nPrintCol
;
1793 nCol
= aColData
.mnCol1
; // move toward 0.
1797 void ScTable::MaybeAddExtraColumn(SCCOL
& rCol
, SCROW nRow
, OutputDevice
* pDev
, double nPPTX
, double nPPTY
)
1799 ScRefCellValue aCell
= aCol
[rCol
].GetCellValue(nRow
);
1800 if (!aCell
.hasString())
1803 bool bFormula
= false; //TODO: pass as parameter
1804 long nPixel
= aCol
[rCol
].GetTextWidth(nRow
);
1806 // Width already calculated in Idle-Handler ?
1807 if ( TEXTWIDTH_DIRTY
== nPixel
)
1809 ScNeededSizeOptions aOptions
;
1810 aOptions
.bTotalSize
= true;
1811 aOptions
.bFormula
= bFormula
;
1812 aOptions
.bSkipMerged
= false;
1814 Fraction
aZoom(1,1);
1815 nPixel
= aCol
[rCol
].GetNeededSize(
1816 nRow
, pDev
, nPPTX
, nPPTY
, aZoom
, aZoom
, true, aOptions
, NULL
);
1818 aCol
[rCol
].SetTextWidth(nRow
, static_cast<sal_uInt16
>(nPixel
));
1821 long nTwips
= (long) (nPixel
/ nPPTX
);
1822 long nDocW
= GetColWidth( rCol
);
1824 long nMissing
= nTwips
- nDocW
;
1827 // look at alignment
1829 const ScPatternAttr
* pPattern
= GetPattern( rCol
, nRow
);
1830 const SfxItemSet
* pCondSet
= pDocument
->GetCondResult( rCol
, nRow
, nTab
);
1832 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)static_cast<const SvxHorJustifyItem
&>(
1833 pPattern
->GetItem( ATTR_HOR_JUSTIFY
, pCondSet
)).GetValue();
1834 if ( eHorJust
== SVX_HOR_JUSTIFY_CENTER
)
1835 nMissing
/= 2; // distributed into both directions
1838 // STANDARD is LEFT (only text is handled here)
1839 bool bRight
= ( eHorJust
== SVX_HOR_JUSTIFY_RIGHT
);
1840 if ( IsLayoutRTL() )
1843 nMissing
= 0; // extended only to the left (logical)
1847 SCCOL nNewCol
= rCol
;
1848 while (nMissing
> 0 && nNewCol
< MAXCOL
)
1850 ScRefCellValue aNextCell
= aCol
[nNewCol
+1].GetCellValue(nRow
);
1851 if (!aNextCell
.isEmpty())
1852 // Cell content in a next column ends display of this string.
1855 nMissing
-= GetColWidth(++nNewCol
);
1862 class SetTableIndex
: public ::std::unary_function
<ScRange
, void>
1866 SetTableIndex(SCTAB nTab
) : mnTab(nTab
) {}
1868 void operator() (ScRange
& rRange
) const
1870 rRange
.aStart
.SetTab(mnTab
);
1871 rRange
.aEnd
.SetTab(mnTab
);
1875 void setPrintRange(ScRange
*& pRange1
, const ScRange
* pRange2
)
1880 *pRange1
= *pRange2
;
1882 pRange1
= new ScRange(*pRange2
);
1890 void ScTable::CopyPrintRange(const ScTable
& rTable
)
1892 // The table index shouldn't be used when the print range is used, but
1893 // just in case set the correct table index.
1895 aPrintRanges
= rTable
.aPrintRanges
;
1896 ::std::for_each(aPrintRanges
.begin(), aPrintRanges
.end(), SetTableIndex(nTab
));
1898 bPrintEntireSheet
= rTable
.bPrintEntireSheet
;
1900 delete pRepeatColRange
;
1901 pRepeatColRange
= NULL
;
1902 if (rTable
.pRepeatColRange
)
1904 pRepeatColRange
= new ScRange(*rTable
.pRepeatColRange
);
1905 pRepeatColRange
->aStart
.SetTab(nTab
);
1906 pRepeatColRange
->aEnd
.SetTab(nTab
);
1909 delete pRepeatRowRange
;
1910 pRepeatRowRange
= NULL
;
1911 if (rTable
.pRepeatRowRange
)
1913 pRepeatRowRange
= new ScRange(*rTable
.pRepeatRowRange
);
1914 pRepeatRowRange
->aStart
.SetTab(nTab
);
1915 pRepeatRowRange
->aEnd
.SetTab(nTab
);
1919 void ScTable::SetRepeatColRange( const ScRange
* pNew
)
1921 setPrintRange( pRepeatColRange
, pNew
);
1923 if (IsStreamValid())
1924 SetStreamValid(false);
1926 InvalidatePageBreaks();
1929 void ScTable::SetRepeatRowRange( const ScRange
* pNew
)
1931 setPrintRange( pRepeatRowRange
, pNew
);
1933 if (IsStreamValid())
1934 SetStreamValid(false);
1936 InvalidatePageBreaks();
1939 void ScTable::ClearPrintRanges()
1941 aPrintRanges
.clear();
1942 bPrintEntireSheet
= false;
1944 if (IsStreamValid())
1945 SetStreamValid(false);
1947 InvalidatePageBreaks(); // #i117952# forget page breaks for an old print range
1950 void ScTable::AddPrintRange( const ScRange
& rNew
)
1952 bPrintEntireSheet
= false;
1953 if( aPrintRanges
.size() < 0xFFFF )
1954 aPrintRanges
.push_back( rNew
);
1956 if (IsStreamValid())
1957 SetStreamValid(false);
1959 InvalidatePageBreaks();
1962 void ScTable::SetPrintEntireSheet()
1964 if( !IsPrintEntireSheet() )
1967 bPrintEntireSheet
= true;
1971 const ScRange
* ScTable::GetPrintRange(sal_uInt16 nPos
) const
1973 return (nPos
< GetPrintRangeCount()) ? &aPrintRanges
[ nPos
] : NULL
;
1976 void ScTable::FillPrintSaver( ScPrintSaverTab
& rSaveTab
) const
1978 rSaveTab
.SetAreas( aPrintRanges
, bPrintEntireSheet
);
1979 rSaveTab
.SetRepeat( pRepeatColRange
, pRepeatRowRange
);
1982 void ScTable::RestorePrintRanges( const ScPrintSaverTab
& rSaveTab
)
1984 aPrintRanges
= rSaveTab
.GetPrintRanges();
1985 bPrintEntireSheet
= rSaveTab
.IsEntireSheet();
1986 SetRepeatColRange( rSaveTab
.GetRepeatCol() );
1987 SetRepeatRowRange( rSaveTab
.GetRepeatRow() );
1989 InvalidatePageBreaks(); // #i117952# forget page breaks for an old print range
1990 UpdatePageBreaks(NULL
);
1993 SCROW
ScTable::VisibleDataCellIterator::ROW_NOT_FOUND
= -1;
1995 ScTable::VisibleDataCellIterator::VisibleDataCellIterator(ScFlatBoolRowSegments
& rRowSegs
, ScColumn
& rColumn
) :
1996 mrRowSegs(rRowSegs
),
1998 mnCurRow(ROW_NOT_FOUND
),
1999 mnUBound(ROW_NOT_FOUND
)
2003 ScTable::VisibleDataCellIterator::~VisibleDataCellIterator()
2007 ScRefCellValue
ScTable::VisibleDataCellIterator::reset(SCROW nRow
)
2011 mnCurRow
= ROW_NOT_FOUND
;
2012 return ScRefCellValue();
2015 ScFlatBoolRowSegments::RangeData aData
;
2016 if (!mrRowSegs
.getRangeData(nRow
, aData
))
2018 mnCurRow
= ROW_NOT_FOUND
;
2019 return ScRefCellValue();
2024 // specified row is visible. Take it.
2026 mnUBound
= aData
.mnRow2
;
2030 // specified row is not-visible. The first visible row is the start of
2031 // the next segment.
2032 mnCurRow
= aData
.mnRow2
+ 1;
2033 mnUBound
= mnCurRow
; // get range data on the next iteration.
2034 if (mnCurRow
> MAXROW
)
2036 // Make sure the row doesn't exceed our current limit.
2037 mnCurRow
= ROW_NOT_FOUND
;
2038 return ScRefCellValue();
2042 maCell
= mrColumn
.GetCellValue(mnCurRow
);
2043 if (!maCell
.isEmpty())
2044 // First visible cell found.
2047 // Find a first visible cell below this row (if any).
2051 ScRefCellValue
ScTable::VisibleDataCellIterator::next()
2053 if (mnCurRow
== ROW_NOT_FOUND
)
2054 return ScRefCellValue();
2056 while (mrColumn
.GetNextDataPos(mnCurRow
))
2058 if (mnCurRow
> mnUBound
)
2060 // We don't know the visibility of this row range. Query it.
2061 ScFlatBoolRowSegments::RangeData aData
;
2062 if (!mrRowSegs
.getRangeData(mnCurRow
, aData
))
2064 mnCurRow
= ROW_NOT_FOUND
;
2065 return ScRefCellValue();
2070 // This row is invisible. Skip to the last invisible row and
2072 mnCurRow
= mnUBound
= aData
.mnRow2
;
2076 // This row is visible.
2077 mnUBound
= aData
.mnRow2
;
2080 maCell
= mrColumn
.GetCellValue(mnCurRow
);
2081 if (!maCell
.isEmpty())
2085 mnCurRow
= ROW_NOT_FOUND
;
2086 return ScRefCellValue();
2089 void ScTable::SetAnonymousDBData(ScDBData
* pDBData
)
2091 delete pDBDataNoName
;
2092 pDBDataNoName
= pDBData
;
2095 sal_uLong
ScTable::AddCondFormat( ScConditionalFormat
* pNew
)
2097 if(!mpCondFormatList
)
2098 mpCondFormatList
.reset(new ScConditionalFormatList());
2101 for(ScConditionalFormatList::const_iterator itr
= mpCondFormatList
->begin();
2102 itr
!= mpCondFormatList
->end(); ++itr
)
2104 sal_uLong nKey
= itr
->GetKey();
2109 pNew
->SetKey(nMax
+1);
2110 mpCondFormatList
->InsertNew(pNew
);
2115 SvtScriptType
ScTable::GetScriptType( SCCOL nCol
, SCROW nRow
) const
2117 if (!ValidCol(nCol
))
2118 return SvtScriptType::NONE
;
2120 return aCol
[nCol
].GetScriptType(nRow
);
2123 void ScTable::SetScriptType( SCCOL nCol
, SCROW nRow
, SvtScriptType nType
)
2125 if (!ValidCol(nCol
))
2128 aCol
[nCol
].SetScriptType(nRow
, nType
);
2131 SvtScriptType
ScTable::GetRangeScriptType(
2132 sc::ColumnBlockPosition
& rBlockPos
, SCCOL nCol
, SCROW nRow1
, SCROW nRow2
)
2134 if (!ValidCol(nCol
))
2135 return SvtScriptType::NONE
;
2137 sc::CellStoreType::iterator itr
= aCol
[nCol
].maCells
.begin();
2138 return aCol
[nCol
].GetRangeScriptType(rBlockPos
.miCellTextAttrPos
, nRow1
, nRow2
, itr
);
2141 size_t ScTable::GetFormulaHash( SCCOL nCol
, SCROW nRow
) const
2143 if (!ValidCol(nCol
))
2146 return aCol
[nCol
].GetFormulaHash(nRow
);
2149 ScFormulaVectorState
ScTable::GetFormulaVectorState( SCCOL nCol
, SCROW nRow
) const
2151 if (!ValidCol(nCol
))
2152 return FormulaVectorUnknown
;
2154 return aCol
[nCol
].GetFormulaVectorState(nRow
);
2157 formula::FormulaTokenRef
ScTable::ResolveStaticReference( SCCOL nCol
, SCROW nRow
)
2159 if (!ValidCol(nCol
) || !ValidRow(nRow
))
2160 return formula::FormulaTokenRef();
2162 return aCol
[nCol
].ResolveStaticReference(nRow
);
2165 formula::FormulaTokenRef
ScTable::ResolveStaticReference( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
2167 if (nCol2
< nCol1
|| nRow2
< nRow1
)
2168 return formula::FormulaTokenRef();
2170 if (!ValidCol(nCol1
) || !ValidCol(nCol2
) || !ValidRow(nRow1
) || !ValidRow(nRow2
))
2171 return formula::FormulaTokenRef();
2173 ScMatrixRef
pMat(new ScMatrix(nCol2
-nCol1
+1, nRow2
-nRow1
+1, 0.0));
2174 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
2176 if (!aCol
[nCol
].ResolveStaticReference(*pMat
, nCol2
-nCol1
, nRow1
, nRow2
))
2177 // Column contains non-static cell. Failed.
2178 return formula::FormulaTokenRef();
2181 return formula::FormulaTokenRef(new ScMatrixToken(pMat
));
2184 formula::VectorRefArray
ScTable::FetchVectorRefArray( SCCOL nCol
, SCROW nRow1
, SCROW nRow2
)
2187 return formula::VectorRefArray();
2189 if (!ValidCol(nCol
) || !ValidRow(nRow1
) || !ValidRow(nRow2
))
2190 return formula::VectorRefArray();
2192 return aCol
[nCol
].FetchVectorRefArray(nRow1
, nRow2
);
2195 ScRefCellValue
ScTable::GetRefCellValue( SCCOL nCol
, SCROW nRow
)
2197 if (!ValidColRow(nCol
, nRow
))
2198 return ScRefCellValue();
2200 return aCol
[nCol
].GetCellValue(nRow
);
2203 SvtBroadcaster
* ScTable::GetBroadcaster( SCCOL nCol
, SCROW nRow
)
2205 if (!ValidColRow(nCol
, nRow
))
2208 return aCol
[nCol
].GetBroadcaster(nRow
);
2211 void ScTable::DeleteBroadcasters(
2212 sc::ColumnBlockPosition
& rBlockPos
, SCCOL nCol
, SCROW nRow1
, SCROW nRow2
)
2214 if (!ValidCol(nCol
))
2217 aCol
[nCol
].DeleteBroadcasters(rBlockPos
, nRow1
, nRow2
);
2220 bool ScTable::HasBroadcaster( SCCOL nCol
) const
2222 if (!ValidCol(nCol
))
2225 return aCol
[nCol
].HasBroadcaster();
2228 void ScTable::FillMatrix( ScMatrix
& rMat
, SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
) const
2231 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
, ++nMatCol
)
2232 aCol
[nCol
].FillMatrix(rMat
, nMatCol
, nRow1
, nRow2
);
2235 void ScTable::InterpretDirtyCells( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
2237 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
2238 aCol
[nCol
].InterpretDirtyCells(nRow1
, nRow2
);
2241 void ScTable::SetFormulaResults( SCCOL nCol
, SCROW nRow
, const double* pResults
, size_t nLen
)
2243 if (!ValidCol(nCol
))
2246 aCol
[nCol
].SetFormulaResults(nRow
, pResults
, nLen
);
2249 void ScTable::SetFormulaResults(
2250 SCCOL nCol
, SCROW nRow
, const formula::FormulaTokenRef
* pResults
, size_t nLen
)
2252 if (!ValidCol(nCol
))
2255 aCol
[nCol
].SetFormulaResults(nRow
, pResults
, nLen
);
2258 #if DEBUG_COLUMN_STORAGE
2259 void ScTable::DumpFormulaGroups( SCCOL nCol
) const
2261 if (!ValidCol(nCol
))
2264 aCol
[nCol
].DumpFormulaGroups();
2268 const SvtBroadcaster
* ScTable::GetBroadcaster( SCCOL nCol
, SCROW nRow
) const
2270 if (!ValidColRow(nCol
, nRow
))
2273 return aCol
[nCol
].GetBroadcaster(nRow
);
2276 void ScTable::DeleteConditionalFormat( sal_uLong nIndex
)
2278 mpCondFormatList
->erase(nIndex
);
2281 void ScTable::SetCondFormList( ScConditionalFormatList
* pNew
)
2283 mpCondFormatList
.reset( pNew
);
2286 ScConditionalFormatList
* ScTable::GetCondFormList()
2288 if(!mpCondFormatList
)
2289 mpCondFormatList
.reset( new ScConditionalFormatList() );
2291 return mpCondFormatList
.get();
2294 const ScConditionalFormatList
* ScTable::GetCondFormList() const
2296 return mpCondFormatList
.get();
2299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */