update dev300-m57
[ooovba.git] / sc / source / core / data / table5.cxx
blobc1bbb440525f44365b9d5ad28daa2b59b2f20005
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: table5.cxx,v $
10 * $Revision: 1.14 $
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"
38 #include "attrib.hxx"
39 #include "patattr.hxx"
40 #include "docpool.hxx"
41 #include "cell.hxx"
42 #include "table.hxx"
43 #include "column.hxx"
44 #include "document.hxx"
45 #include "drwlayer.hxx"
46 #include "olinetab.hxx"
47 #include "userlist.hxx"
48 #include "stlsheet.hxx"
49 #include "global.hxx"
50 #include "rechead.hxx"
51 #include "stlpool.hxx"
52 #include "stlsheet.hxx"
53 #include "brdcst.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() )
67 return;
68 if ( !pUserArea && !bPageSizeValid )
69 return;
71 SfxStyleSheetBase* pStyle = pDocument->GetStyleSheetPool()->
72 Find( aPageStyle, SFX_STYLE_FAMILY_PAGE );
73 if ( !pStyle )
75 DBG_ERROR("UpdatePageBreaks: Style nicht gefunden");
76 return;
78 SfxItemSet* pStyleSet = &pStyle->GetItemSet();
79 const SfxPoolItem* pItem;
81 SCCOL nX;
82 SCROW nY;
83 SCCOL nStartCol = 0;
84 SCROW nStartRow = 0;
85 SCCOL nEndCol = MAXCOL;
86 SCROW nEndRow = MAXROW;
87 if (pUserArea)
89 nStartCol = pUserArea->aStart.Col();
90 nStartRow = pUserArea->aStart.Row();
91 nEndCol = pUserArea->aEnd.Col();
92 nEndRow = pUserArea->aEnd.Row();
94 else
96 USHORT nAreaCount = GetPrintRangeCount();
97 if ( nAreaCount > 1 )
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) );
105 return;
107 else if ( nAreaCount == 1 )
109 const ScRange* pArea = GetPrintRange( 0 );
110 if (pArea)
112 nStartCol = pArea->aStart.Col();
113 nStartRow = pArea->aStart.Row();
114 nEndCol = pArea->aEnd.Col();
115 nEndRow = pArea->aEnd.Row();
117 } // sonst alles
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.
136 bSkipBreaks = true;
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) );
150 if (nStartCol > 0)
151 pColFlags[nStartCol] |= CR_PAGEBREAK; //! AREABREAK
152 if (nStartRow > 0)
153 pRowFlags->OrValue( nStartRow, CR_PAGEBREAK); //! AREABREAK
155 // Mittelteil: Breaks verteilen
157 BOOL bRepeatCol = ( nRepeatStartX != SCCOL_REPEAT_NONE );
158 BOOL bColFound = FALSE;
159 long nSizeX = 0;
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;
167 nSizeX = 0;
168 bStartOfPage = TRUE;
170 else if (nX != nStartCol)
171 pColFlags[nX] &= ~CR_PAGEBREAK;
172 else
173 bStartOfPage = TRUE;
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;
182 bColFound = TRUE;
185 nSizeX += nThisX;
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;
193 long nSizeY = 0;
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);
206 nSizeY = 0;
207 bStartOfPage = TRUE;
209 else if (nY != nStartRow)
210 ; // page break already removed
211 else
212 bStartOfPage = TRUE;
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);
219 #ifdef DBG_UTIL
220 if (nHeights == ::std::numeric_limits<unsigned long>::max())
221 DBG_ERRORFILE("ScTable::UpdatePageBreaks: row heights overflow");
222 #endif
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);
231 bRowFound = TRUE;
234 nSizeY += nThisY;
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()
255 if (pColFlags)
256 for (SCCOL nCol = 0; nCol <= MAXCOL; nCol++)
257 pColFlags[nCol] &= ~CR_MANUALBREAK;
259 if (pRowFlags)
260 pRowFlags->AndValue( 0, MAXROW, sal::static_int_cast<BYTE>(~CR_MANUALBREAK) );
263 BOOL ScTable::HasManualBreaks() const
265 if (pColFlags)
266 for (SCCOL nCol = 0; nCol <= MAXCOL; nCol++)
267 if ( pColFlags[nCol] & CR_MANUALBREAK )
268 return TRUE;
270 if (pRowFlags)
271 if (ValidRow( pRowFlags->GetLastAnyBitAccess( 0, CR_MANUALBREAK)))
272 return TRUE;
274 return FALSE;
277 void ScTable::SetPageSize( const Size& rSize )
279 if ( rSize.Width() != 0 && rSize.Height() != 0 )
281 bPageSizeValid = TRUE;
282 aPageSizeTwips = rSize;
284 else
285 bPageSizeValid = FALSE;
288 BOOL ScTable::IsProtected() const
290 return pTabProtection.get() && pTabProtection->isProtected();
293 void ScTable::SetProtection(const ScTableProtection* pProtect)
295 if (pProtect)
296 pTabProtection.reset(new ScTableProtection(*pProtect));
297 else
298 pTabProtection.reset(NULL);
301 ScTableProtection* ScTable::GetProtection()
303 return pTabProtection.get();
306 Size ScTable::GetPageSize() const
308 if ( bPageSizeValid )
309 return aPageSizeTwips;
310 else
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 );
340 if ( !pNewStyle )
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() );
381 if ( pCell )
383 pCell->SetTextWidth( TEXTWIDTH_DIRTY );
384 if ( bNumFormatChanged )
385 pCell->SetScriptType( SC_SCRIPTTYPE_UNKNOWN );
386 if ( bBroadcast )
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 ),
393 pCell );
394 break;
395 case CELLTYPE_FORMULA :
396 ((ScFormulaCell*)pCell)->SetDirty();
397 break;
398 default:
400 // added to avoid warnings
406 else
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 );
424 if ( bBroadcast )
425 { // nur bei CalcAsShown
426 switch ( pCell->GetCellType() )
428 case CELLTYPE_VALUE :
429 pDocument->Broadcast( SC_HINT_DATACHANGED,
430 ScAddress( nCol, nRow, nTab ), pCell );
431 break;
432 case CELLTYPE_FORMULA :
433 ((ScFormulaCell*)pCell)->SetDirty();
434 break;
435 default:
437 // added to avoid warnings