1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: table5.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #include "scitems.hxx"
37 #include "collect.hxx"
39 #include "patattr.hxx"
40 #include "docpool.hxx"
44 #include "document.hxx"
45 #include "drwlayer.hxx"
46 #include "olinetab.hxx"
47 #include "userlist.hxx"
48 #include "stlsheet.hxx"
50 #include "rechead.hxx"
51 #include "stlpool.hxx"
52 #include "stlsheet.hxx"
54 #include "tabprotection.hxx"
55 #include "globstr.hrc"
57 using ::com::sun::star::uno::Sequence
;
59 // STATIC DATA -----------------------------------------------------------
61 #define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue()
64 void ScTable::UpdatePageBreaks( const ScRange
* pUserArea
)
66 if ( pDocument
->IsImportingXML() )
68 if ( !pUserArea
&& !bPageSizeValid
)
71 SfxStyleSheetBase
* pStyle
= pDocument
->GetStyleSheetPool()->
72 Find( aPageStyle
, SFX_STYLE_FAMILY_PAGE
);
75 DBG_ERROR("UpdatePageBreaks: Style nicht gefunden");
78 SfxItemSet
* pStyleSet
= &pStyle
->GetItemSet();
79 const SfxPoolItem
* pItem
;
85 SCCOL nEndCol
= MAXCOL
;
86 SCROW nEndRow
= MAXROW
;
89 nStartCol
= pUserArea
->aStart
.Col();
90 nStartRow
= pUserArea
->aStart
.Row();
91 nEndCol
= pUserArea
->aEnd
.Col();
92 nEndRow
= pUserArea
->aEnd
.Row();
96 USHORT nAreaCount
= GetPrintRangeCount();
99 // bei mehreren Bereichen nichts anzeigen:
101 for (nX
=0; nX
<MAXCOL
; nX
++)
102 pColFlags
[nX
] &= ~CR_PAGEBREAK
;
103 pRowFlags
->AndValue( 0, MAXROW
-1, sal::static_int_cast
<BYTE
>(~CR_PAGEBREAK
) );
107 else if ( nAreaCount
== 1 )
109 const ScRange
* pArea
= GetPrintRange( 0 );
112 nStartCol
= pArea
->aStart
.Col();
113 nStartRow
= pArea
->aStart
.Row();
114 nEndCol
= pArea
->aEnd
.Col();
115 nEndRow
= pArea
->aEnd
.Row();
120 // bSkipBreaks holen:
122 BOOL bSkipBreaks
= FALSE
;
124 if ( pStyleSet
->GetItemState( ATTR_PAGE_SCALETOPAGES
, FALSE
, &pItem
) == SFX_ITEM_SET
)
126 DBG_ASSERT( pItem
->ISA(SfxUInt16Item
), "falsches Item" );
127 bSkipBreaks
= ( ((const SfxUInt16Item
*)pItem
)->GetValue() > 0 );
130 if (!bSkipBreaks
&& pStyleSet
->GetItemState(ATTR_PAGE_SCALETO
, false, &pItem
) == SFX_ITEM_SET
)
132 const ScPageScaleToItem
& rScaleToItem
= static_cast<const ScPageScaleToItem
&>(
133 pStyleSet
->Get(ATTR_PAGE_SCALETO
));
134 if (rScaleToItem
.GetWidth() > 0 || rScaleToItem
.GetHeight() > 0)
135 // when fitting to a fixed width x height, ignore manual breaks.
139 //--------------------------------------------------------------------------
141 long nPageSizeX
= aPageSizeTwips
.Width();
142 long nPageSizeY
= aPageSizeTwips
.Height();
144 // Anfang: Breaks loeschen
146 for (nX
=0; nX
<nStartCol
; nX
++)
147 pColFlags
[nX
] &= ~CR_PAGEBREAK
;
148 pRowFlags
->AndValue( 0, nStartRow
-1, sal::static_int_cast
<BYTE
>(~CR_PAGEBREAK
) );
151 pColFlags
[nStartCol
] |= CR_PAGEBREAK
; //! AREABREAK
153 pRowFlags
->OrValue( nStartRow
, CR_PAGEBREAK
); //! AREABREAK
155 // Mittelteil: Breaks verteilen
157 BOOL bRepeatCol
= ( nRepeatStartX
!= SCCOL_REPEAT_NONE
);
158 BOOL bColFound
= FALSE
;
160 for (nX
=nStartCol
; nX
<=nEndCol
; nX
++)
162 BOOL bStartOfPage
= FALSE
;
163 long nThisX
= ( pColFlags
[nX
] & CR_HIDDEN
) ? 0 : pColWidth
[nX
];
164 if ( (nSizeX
+nThisX
> nPageSizeX
) || ((pColFlags
[nX
] & CR_MANUALBREAK
) && !bSkipBreaks
) )
166 pColFlags
[nX
] |= CR_PAGEBREAK
;
170 else if (nX
!= nStartCol
)
171 pColFlags
[nX
] &= ~CR_PAGEBREAK
;
175 if ( bStartOfPage
&& bRepeatCol
&& nX
>nRepeatStartX
&& !bColFound
)
177 // subtract size of repeat columns from page size
178 for (SCCOL i
=nRepeatStartX
; i
<=nRepeatEndX
; i
++)
179 nPageSizeX
-= ( pColFlags
[i
] & CR_HIDDEN
) ? 0 : pColWidth
[i
];
180 while (nX
<=nRepeatEndX
)
181 pColFlags
[++nX
] &= ~CR_PAGEBREAK
;
188 // Remove all page breaks in range.
189 pRowFlags
->AndValue( nStartRow
+1, nEndRow
, sal::static_int_cast
<BYTE
>(~CR_PAGEBREAK
) );
190 // And set new page breaks.
191 BOOL bRepeatRow
= ( nRepeatStartY
!= SCROW_REPEAT_NONE
);
192 BOOL bRowFound
= FALSE
;
194 ScCompressedArrayIterator
< SCROW
, BYTE
> aFlagsIter( *pRowFlags
, nStartRow
, nEndRow
);
195 ScCompressedArrayIterator
< SCROW
, USHORT
> aHeightIter( *pRowHeight
, nStartRow
, nEndRow
);
196 for ( ; aFlagsIter
; ++aFlagsIter
, ++aHeightIter
)
198 nY
= aFlagsIter
.GetPos();
199 BOOL bStartOfPage
= FALSE
;
200 BYTE nFlags
= *aFlagsIter
;
201 long nThisY
= (nFlags
& CR_HIDDEN
) ? 0 : *aHeightIter
;
202 if ( (nSizeY
+nThisY
> nPageSizeY
) || ((nFlags
& CR_MANUALBREAK
) && !bSkipBreaks
) )
204 pRowFlags
->SetValue( nY
, nFlags
| CR_PAGEBREAK
);
205 aFlagsIter
.Resync( nY
);
209 else if (nY
!= nStartRow
)
210 ; // page break already removed
214 if ( bStartOfPage
&& bRepeatRow
&& nY
>nRepeatStartY
&& !bRowFound
)
216 // subtract size of repeat rows from page size
217 unsigned long nHeights
= pRowFlags
->SumCoupledArrayForCondition(
218 nRepeatStartY
, nRepeatEndY
, CR_HIDDEN
, 0, *pRowHeight
);
220 if (nHeights
== ::std::numeric_limits
<unsigned long>::max())
221 DBG_ERRORFILE("ScTable::UpdatePageBreaks: row heights overflow");
223 nPageSizeY
-= nHeights
;
224 if (nY
<= nRepeatEndY
)
226 pRowFlags
->AndValue( nY
, nRepeatEndY
, sal::static_int_cast
<BYTE
>(~CR_PAGEBREAK
) );
227 nY
= nRepeatEndY
+ 1;
228 aFlagsIter
.Resync( nY
);
229 aHeightIter
.Resync( nY
);
237 // Ende: Breaks loeschen
239 if (nEndCol
< MAXCOL
)
241 pColFlags
[nEndCol
+1] |= CR_PAGEBREAK
; //! AREABREAK
242 for (nX
=nEndCol
+2; nX
<=MAXCOL
; nX
++)
243 pColFlags
[nX
] &= ~CR_PAGEBREAK
;
245 if (nEndRow
< MAXROW
)
247 pRowFlags
->OrValue( nEndRow
+1, CR_PAGEBREAK
); //! AREABREAK
248 if (nEndRow
+2 <= MAXROW
)
249 pRowFlags
->AndValue( nEndRow
+2, MAXROW
, sal::static_int_cast
<BYTE
>(~CR_PAGEBREAK
) );
253 void ScTable::RemoveManualBreaks()
256 for (SCCOL nCol
= 0; nCol
<= MAXCOL
; nCol
++)
257 pColFlags
[nCol
] &= ~CR_MANUALBREAK
;
260 pRowFlags
->AndValue( 0, MAXROW
, sal::static_int_cast
<BYTE
>(~CR_MANUALBREAK
) );
263 BOOL
ScTable::HasManualBreaks() const
266 for (SCCOL nCol
= 0; nCol
<= MAXCOL
; nCol
++)
267 if ( pColFlags
[nCol
] & CR_MANUALBREAK
)
271 if (ValidRow( pRowFlags
->GetLastAnyBitAccess( 0, CR_MANUALBREAK
)))
277 void ScTable::SetPageSize( const Size
& rSize
)
279 if ( rSize
.Width() != 0 && rSize
.Height() != 0 )
281 bPageSizeValid
= TRUE
;
282 aPageSizeTwips
= rSize
;
285 bPageSizeValid
= FALSE
;
288 BOOL
ScTable::IsProtected() const
290 return pTabProtection
.get() && pTabProtection
->isProtected();
293 void ScTable::SetProtection(const ScTableProtection
* pProtect
)
296 pTabProtection
.reset(new ScTableProtection(*pProtect
));
298 pTabProtection
.reset(NULL
);
301 ScTableProtection
* ScTable::GetProtection()
303 return pTabProtection
.get();
306 Size
ScTable::GetPageSize() const
308 if ( bPageSizeValid
)
309 return aPageSizeTwips
;
311 return Size(); // leer
314 void ScTable::SetRepeatArea( SCCOL nStartCol
, SCCOL nEndCol
, SCROW nStartRow
, SCROW nEndRow
)
316 nRepeatStartX
= nStartCol
;
317 nRepeatEndX
= nEndCol
;
318 nRepeatStartY
= nStartRow
;
319 nRepeatEndY
= nEndRow
;
322 void ScTable::StartListening( const ScAddress
& rAddress
, SvtListener
* pListener
)
324 aCol
[rAddress
.Col()].StartListening( *pListener
, rAddress
.Row() );
327 void ScTable::EndListening( const ScAddress
& rAddress
, SvtListener
* pListener
)
329 aCol
[rAddress
.Col()].EndListening( *pListener
, rAddress
.Row() );
332 void ScTable::SetPageStyle( const String
& rName
)
334 if ( aPageStyle
!= rName
)
336 String aStrNew
= rName
;
337 SfxStyleSheetBasePool
* pStylePool
= pDocument
->GetStyleSheetPool();
338 SfxStyleSheetBase
* pNewStyle
= pStylePool
->Find( aStrNew
, SFX_STYLE_FAMILY_PAGE
);
342 aStrNew
= ScGlobal::GetRscString(STR_STYLENAME_STANDARD
);
343 pNewStyle
= pStylePool
->Find( aStrNew
, SFX_STYLE_FAMILY_PAGE
);
346 if ( aPageStyle
!= aStrNew
)
348 SfxStyleSheetBase
* pOldStyle
= pStylePool
->Find( aPageStyle
, SFX_STYLE_FAMILY_PAGE
);
350 if ( pOldStyle
&& pNewStyle
)
352 SfxItemSet
& rOldSet
= pOldStyle
->GetItemSet();
353 SfxItemSet
& rNewSet
= pNewStyle
->GetItemSet();
354 const USHORT nOldScale
= GET_SCALEVALUE(rOldSet
,ATTR_PAGE_SCALE
);
355 const USHORT nOldScaleToPages
= GET_SCALEVALUE(rOldSet
,ATTR_PAGE_SCALETOPAGES
);
356 const USHORT nNewScale
= GET_SCALEVALUE(rNewSet
,ATTR_PAGE_SCALE
);
357 const USHORT nNewScaleToPages
= GET_SCALEVALUE(rNewSet
,ATTR_PAGE_SCALETOPAGES
);
359 if ( (nOldScale
!= nNewScale
) || (nOldScaleToPages
!= nNewScaleToPages
) )
360 InvalidateTextWidth(NULL
, NULL
, FALSE
, FALSE
);
363 if ( pNewStyle
) // auch ohne den alten (fuer UpdateStdNames)
364 aPageStyle
= aStrNew
;
369 void ScTable::PageStyleModified( const String
& rNewName
)
371 aPageStyle
= rNewName
;
372 InvalidateTextWidth(NULL
, NULL
, FALSE
, FALSE
); // don't know what was in the style before
375 void ScTable::InvalidateTextWidth( const ScAddress
* pAdrFrom
, const ScAddress
* pAdrTo
,
376 BOOL bNumFormatChanged
, BOOL bBroadcast
)
378 if ( pAdrFrom
&& !pAdrTo
)
380 ScBaseCell
* pCell
= aCol
[pAdrFrom
->Col()].GetCell( pAdrFrom
->Row() );
383 pCell
->SetTextWidth( TEXTWIDTH_DIRTY
);
384 if ( bNumFormatChanged
)
385 pCell
->SetScriptType( SC_SCRIPTTYPE_UNKNOWN
);
387 { // nur bei CalcAsShown
388 switch ( pCell
->GetCellType() )
390 case CELLTYPE_VALUE
:
391 pDocument
->Broadcast( SC_HINT_DATACHANGED
,
392 ScAddress( pAdrFrom
->Col(), pAdrFrom
->Row(), nTab
),
395 case CELLTYPE_FORMULA
:
396 ((ScFormulaCell
*)pCell
)->SetDirty();
400 // added to avoid warnings
408 const SCCOL nColStart
= pAdrFrom
? pAdrFrom
->Col() : 0;
409 const SCROW nRowStart
= pAdrFrom
? pAdrFrom
->Row() : 0;
410 const SCCOL nColEnd
= pAdrTo
? pAdrTo
->Col() : MAXCOL
;
411 const SCROW nRowEnd
= pAdrTo
? pAdrTo
->Row() : MAXROW
;
413 for ( SCCOL nCol
=nColStart
; nCol
<=nColEnd
; nCol
++ )
415 ScColumnIterator
aIter( &aCol
[nCol
], nRowStart
, nRowEnd
);
416 ScBaseCell
* pCell
= NULL
;
417 SCROW nRow
= nRowStart
;
419 while ( aIter
.Next( nRow
, pCell
) )
421 pCell
->SetTextWidth( TEXTWIDTH_DIRTY
);
422 if ( bNumFormatChanged
)
423 pCell
->SetScriptType( SC_SCRIPTTYPE_UNKNOWN
);
425 { // nur bei CalcAsShown
426 switch ( pCell
->GetCellType() )
428 case CELLTYPE_VALUE
:
429 pDocument
->Broadcast( SC_HINT_DATACHANGED
,
430 ScAddress( nCol
, nRow
, nTab
), pCell
);
432 case CELLTYPE_FORMULA
:
433 ((ScFormulaCell
*)pCell
)->SetDirty();
437 // added to avoid warnings