update dev300-m57
[ooovba.git] / sc / source / core / data / fillinfo.cxx
blob54ffe10b02e427bb8ab0171d615c014327d6305f
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: fillinfo.cxx,v $
10 * $Revision: 1.15 $
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"
36 // INCLUDE ---------------------------------------------------------------
38 #include "scitems.hxx"
39 #include <svx/boxitem.hxx>
40 #include <svx/bolnitem.hxx>
41 #include <svx/editdata.hxx> // can be removed if table has a bLayoutRTL flag
42 #include <svx/shaditem.hxx>
44 #include "fillinfo.hxx"
45 #include "document.hxx"
46 #include "cell.hxx"
47 #include "table.hxx"
48 #include "attrib.hxx"
49 #include "attarray.hxx"
50 #include "markarr.hxx"
51 #include "markdata.hxx"
52 #include "patattr.hxx"
53 #include "poolhelp.hxx"
54 #include "docpool.hxx"
55 #include "conditio.hxx"
56 #include "stlpool.hxx"
59 // -----------------------------------------------------------------------
61 const USHORT ROWINFO_MAX = 1024;
64 enum FillInfoLinePos
66 FILP_TOP,
67 FILP_BOTTOM,
68 FILP_LEFT,
69 FILP_RIGHT
73 inline const SvxBorderLine* GetNullOrLine( const SvxBoxItem* pBox, FillInfoLinePos eWhich )
75 if (pBox)
77 if (eWhich==FILP_TOP)
78 return pBox->GetTop();
79 else if (eWhich==FILP_BOTTOM)
80 return pBox->GetBottom();
81 else if (eWhich==FILP_LEFT)
82 return pBox->GetLeft();
83 else
84 return pBox->GetRight();
86 else
87 return NULL;
90 // aehnlich wie in output.cxx
92 void lcl_GetMergeRange( SCsCOL nX, SCsROW nY, SCSIZE nArrY,
93 ScDocument* pDoc, RowInfo* pRowInfo,
94 SCCOL nX1, SCROW nY1, SCCOL /* nX2 */, SCROW /* nY2 */, SCTAB nTab,
95 SCsCOL& rStartX, SCsROW& rStartY, SCsCOL& rEndX, SCsROW& rEndY )
97 CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1];
99 rStartX = nX;
100 rStartY = nY;
101 BOOL bHOver = pInfo->bHOverlapped;
102 BOOL bVOver = pInfo->bVOverlapped;
104 while (bHOver) // nY konstant
106 --rStartX;
107 if (rStartX >= (SCsCOL) nX1 && (pDoc->GetColFlags(rStartX,nTab) & CR_HIDDEN) == 0)
109 bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped;
110 bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped;
112 else
114 USHORT nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
115 rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue();
116 bHOver = ((nOverlap & SC_MF_HOR) != 0);
117 bVOver = ((nOverlap & SC_MF_VER) != 0);
121 while (bVOver)
123 --rStartY;
125 if (nArrY>0)
126 --nArrY; // lokale Kopie !
128 if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 &&
129 (pDoc->GetColFlags(rStartX,nTab) & CR_HIDDEN) == 0 &&
130 (pDoc->GetRowFlags(rStartY,nTab) & CR_HIDDEN) == 0 &&
131 (SCsROW) pRowInfo[nArrY].nRowNo == rStartY)
133 bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped;
134 bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped;
136 else
138 USHORT nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
139 rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue();
140 bHOver = ((nOverlap & SC_MF_HOR) != 0);
141 bVOver = ((nOverlap & SC_MF_VER) != 0);
145 const ScMergeAttr* pMerge;
146 if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 &&
147 (pDoc->GetColFlags(rStartX,nTab) & CR_HIDDEN) == 0 &&
148 (pDoc->GetRowFlags(rStartY,nTab) & CR_HIDDEN) == 0 &&
149 (SCsROW) pRowInfo[nArrY].nRowNo == rStartY)
151 pMerge = (const ScMergeAttr*) &pRowInfo[nArrY].pCellInfo[rStartX+1].pPatternAttr->
152 GetItem(ATTR_MERGE);
154 else
155 pMerge = (const ScMergeAttr*) pDoc->GetAttr(rStartX,rStartY,nTab,ATTR_MERGE);
157 rEndX = rStartX + pMerge->GetColMerge() - 1;
158 rEndY = rStartY + pMerge->GetRowMerge() - 1;
161 inline BOOL ScDocument::RowHidden( SCROW nRow, SCTAB nTab )
163 return ( pTab[nTab]->pRowFlags->GetValue(nRow) & CR_HIDDEN ) != 0;
167 #define CELLINFO(x,y) pRowInfo[nArrY+y].pCellInfo[nArrX+x]
169 void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
170 SCTAB nTab, double nScaleX, double nScaleY,
171 BOOL bPageMode, BOOL bFormulaMode, const ScMarkData* pMarkData )
173 DBG_ASSERT( pTab[nTab], "Tabelle existiert nicht" );
175 BOOL bLayoutRTL = IsLayoutRTL( nTab );
177 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
178 ScStyleSheetPool* pStlPool = xPoolHelper->GetStylePool();
180 RowInfo* pRowInfo = rTabInfo.mpRowInfo;
182 const SvxBrushItem* pDefBackground =
183 (const SvxBrushItem*) &pPool->GetDefaultItem( ATTR_BACKGROUND );
184 const ScMergeAttr* pDefMerge =
185 (const ScMergeAttr*) &pPool->GetDefaultItem( ATTR_MERGE );
186 const SvxShadowItem* pDefShadow =
187 (const SvxShadowItem*) &pPool->GetDefaultItem( ATTR_SHADOW );
189 SCROW nThisRow;
190 SCCOL nX;
191 SCROW nY;
192 SCsROW nSignedY;
193 SCCOL nArrX;
194 SCSIZE nArrY;
195 SCSIZE nArrCount;
196 BOOL bAnyMerged = FALSE;
197 BOOL bAnyShadow = FALSE;
198 BOOL bAnyCondition = FALSE;
200 BOOL bTabProtect = IsTabProtected(nTab);
202 // fuer Blockmarken von zusammengefassten Zellen mit
203 // versteckter erster Zeile / Spalte
204 BOOL bPaintMarks = FALSE;
205 BOOL bSkipMarks = FALSE;
206 SCCOL nBlockStartX = 0, nBlockEndX = 0;
207 SCROW nBlockEndY = 0, nBlockStartY = 0;
208 if (pMarkData && pMarkData->IsMarked())
210 ScRange aTmpRange;
211 pMarkData->GetMarkArea(aTmpRange);
212 if ( nTab >= aTmpRange.aStart.Tab() && nTab <= aTmpRange.aEnd.Tab() )
214 nBlockStartX = aTmpRange.aStart.Col();
215 nBlockStartY = aTmpRange.aStart.Row();
216 nBlockEndX = aTmpRange.aEnd.Col();
217 nBlockEndY = aTmpRange.aEnd.Row();
218 ExtendHidden( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY, nTab ); //? noetig ?
219 if (pMarkData->IsMarkNegative())
220 bSkipMarks = TRUE;
221 else
222 bPaintMarks = TRUE;
226 // zuerst nur die Eintraege fuer die ganze Spalte
228 nArrY=0;
229 SCROW nYExtra = nY2+1;
230 for (nSignedY=((SCsROW)nY1)-1; nSignedY<=(SCsROW)nYExtra; nSignedY++)
232 if (nSignedY >= 0)
233 nY = (SCROW) nSignedY;
234 else
235 nY = MAXROW+1; // ungueltig
237 USHORT nDocHeight;
238 if (ValidRow(nY))
239 nDocHeight = GetRowHeight( nY, nTab );
240 else
241 nDocHeight = ScGlobal::nStdRowHeight;
243 if ( nArrY==0 || nDocHeight || nY > MAXROW )
245 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
246 pThisRowInfo->pCellInfo = NULL; // wird unten belegt
248 USHORT nHeight = (USHORT) ( nDocHeight * nScaleY );
249 if (!nHeight)
250 nHeight = 1;
252 pThisRowInfo->nRowNo = nY; //! Fall < 0 ?
253 pThisRowInfo->nHeight = nHeight;
254 pThisRowInfo->bEmptyBack = TRUE;
255 pThisRowInfo->bEmptyText = TRUE;
256 pThisRowInfo->bChanged = TRUE;
257 pThisRowInfo->bAutoFilter = FALSE;
258 pThisRowInfo->bPushButton = FALSE;
259 pThisRowInfo->nRotMaxCol = SC_ROTMAX_NONE;
261 ++nArrY;
262 if (nArrY >= ROWINFO_MAX)
264 DBG_ERROR("Zu grosser Bereich bei FillInfo" );
265 nYExtra = nSignedY; // Ende
266 nY2 = nYExtra - 1; // Bereich anpassen
269 else
270 if (nSignedY==(SCsROW) nYExtra) // zusaetzliche Zeile verdeckt ?
271 ++nYExtra;
273 nArrCount = nArrY; // incl. Dummys
275 // rotierter Text...
277 // Attribut im Dokument ueberhaupt verwendet?
278 BOOL bAnyItem = FALSE;
279 USHORT nRotCount = pPool->GetItemCount( ATTR_ROTATE_VALUE );
280 for (USHORT nItem=0; nItem<nRotCount; nItem++)
281 if (pPool->GetItem( ATTR_ROTATE_VALUE, nItem ))
283 bAnyItem = TRUE;
284 break;
287 SCCOL nRotMax = nX2;
288 if ( bAnyItem && HasAttrib( 0,nY1,nTab, MAXCOL,nY2+1,nTab,
289 HASATTR_ROTATE | HASATTR_CONDITIONAL ) )
291 //! Conditionals auch bei HASATTR_ROTATE abfragen ????
293 DBG_ASSERT( nArrCount>2, "nArrCount zu klein" );
294 // FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-2, nX1, nX2 );
295 FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-1, nX1, nX2 );
296 // FindMaxRotCol setzt nRotMaxCol
298 for (nArrY=0; nArrY<nArrCount; nArrY++)
299 if (pRowInfo[nArrY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nArrY].nRotMaxCol > nRotMax)
300 nRotMax = pRowInfo[nArrY].nRotMaxCol;
303 // Zell-Infos erst nach dem Test auf gedrehte allozieren
304 // bis nRotMax wegen nRotateDir Flag
306 for (nArrY=0; nArrY<nArrCount; nArrY++)
308 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
309 nY = pThisRowInfo->nRowNo;
310 pThisRowInfo->pCellInfo = new CellInfo[ nRotMax+1+2 ]; // vom Aufrufer zu loeschen !
312 for (nArrX=0; nArrX<=nRotMax+2; nArrX++) // Zell-Infos vorbelegen
314 if (nArrX>0)
315 nX = nArrX-1;
316 else
317 nX = MAXCOL+1; // ungueltig
319 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
320 pInfo->bEmptyCellText = TRUE;
321 pInfo->pCell = NULL;
322 if (bPaintMarks)
323 pInfo->bMarked = ( nX >= nBlockStartX && nX <= nBlockEndX
324 && nY >= nBlockStartY && nY <= nBlockEndY );
325 else
326 pInfo->bMarked = FALSE;
327 pInfo->nWidth = 0;
329 pInfo->nClipMark = SC_CLIPMARK_NONE;
330 pInfo->bMerged = FALSE;
331 pInfo->bHOverlapped = FALSE;
332 pInfo->bVOverlapped = FALSE;
333 pInfo->bAutoFilter = FALSE;
334 pInfo->bPushButton = FALSE;
335 pInfo->bPopupButton = false;
336 pInfo->bFilterActive = false;
337 pInfo->nRotateDir = SC_ROTDIR_NONE;
339 pInfo->bPrinted = FALSE; // view-intern
340 pInfo->bHideGrid = FALSE; // view-intern
341 pInfo->bEditEngine = FALSE; // view-intern
343 pInfo->pBackground = NULL; //! weglassen?
344 pInfo->pPatternAttr = NULL;
345 pInfo->pConditionSet= NULL;
347 pInfo->pLinesAttr = NULL;
348 pInfo->mpTLBRLine = NULL;
349 pInfo->mpBLTRLine = NULL;
351 pInfo->pShadowAttr = pDefShadow;
352 pInfo->pHShadowOrigin = NULL;
353 pInfo->pVShadowOrigin = NULL;
357 for (nArrX=nX2+3; nArrX<=nRotMax+2; nArrX++) // restliche Breiten eintragen
359 nX = nArrX-1;
360 if ( ValidCol(nX) )
362 if ( (GetColFlags(nX,nTab) & CR_HIDDEN) == 0 ) // Spalte nicht versteckt
364 USHORT nThisWidth = (USHORT) (GetColWidth( nX, nTab ) * nScaleX);
365 if (!nThisWidth)
366 nThisWidth = 1;
368 pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth;
373 for (nArrX=0; nArrX<=nX2+2; nArrX++) // links & rechts + 1
375 nX = (nArrX>0) ? nArrX-1 : MAXCOL+1; // negativ -> ungueltig
377 if ( ValidCol(nX) )
379 // #i58049#, #i57939# Hidden columns must be skipped here, or their attributes
380 // will disturb the output
382 if ( (GetColFlags(nX,nTab) & CR_HIDDEN) == 0 ) // column not hidden
384 USHORT nThisWidth = (USHORT) (GetColWidth( nX, nTab ) * nScaleX);
385 if (!nThisWidth)
386 nThisWidth = 1;
388 pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth; //! dies sollte reichen
390 ScColumn* pThisCol = &pTab[nTab]->aCol[nX]; // Spalten-Daten
392 nArrY = 1;
393 SCSIZE nUIndex;
394 (void) pThisCol->Search( nY1, nUIndex );
395 while ( nUIndex < pThisCol->nCount &&
396 (nThisRow=pThisCol->pItems[nUIndex].nRow) <= nY2 )
398 if ( !RowHidden( nThisRow,nTab ) )
400 while ( pRowInfo[nArrY].nRowNo < nThisRow )
401 ++nArrY;
402 DBG_ASSERT( pRowInfo[nArrY].nRowNo == nThisRow, "Zeile nicht gefunden in FillInfo" );
404 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
405 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
406 pInfo->pCell = pThisCol->pItems[nUIndex].pCell;
407 if (pInfo->pCell->GetCellType() != CELLTYPE_NOTE)
409 pThisRowInfo->bEmptyText = FALSE; // Zeile nicht leer
410 pInfo->bEmptyCellText = FALSE; // Zelle nicht leer
412 ++nArrY;
414 ++nUIndex;
417 if (nX+1 >= nX1) // Attribute/Blockmarken ab nX1-1
419 ScAttrArray* pThisAttrArr = pThisCol->pAttrArray; // Attribute
421 nArrY = 0;
422 const ScPatternAttr* pPattern;
423 SCROW nCurRow=nY1; // einzelne Zeile
424 if (nCurRow>0)
425 --nCurRow; // oben 1 mehr
426 else
427 nArrY = 1;
428 nThisRow=nCurRow; // Ende des Bereichs
429 SCSIZE nIndex;
430 (void) pThisAttrArr->Search( nCurRow, nIndex );
435 nThisRow=pThisAttrArr->pData[nIndex].nRow; // Ende des Bereichs
436 pPattern=pThisAttrArr->pData[nIndex].pPattern;
438 const SvxBrushItem* pBackground = (const SvxBrushItem*)
439 &pPattern->GetItem(ATTR_BACKGROUND);
440 const SvxBoxItem* pLinesAttr = (const SvxBoxItem*)
441 &pPattern->GetItem(ATTR_BORDER);
443 const SvxLineItem* pTLBRLine = static_cast< const SvxLineItem* >(
444 &pPattern->GetItem( ATTR_BORDER_TLBR ) );
445 const SvxLineItem* pBLTRLine = static_cast< const SvxLineItem* >(
446 &pPattern->GetItem( ATTR_BORDER_BLTR ) );
448 const SvxShadowItem* pShadowAttr = (const SvxShadowItem*)
449 &pPattern->GetItem(ATTR_SHADOW);
450 if (pShadowAttr != pDefShadow)
451 bAnyShadow = TRUE;
453 const ScMergeAttr* pMergeAttr = (const ScMergeAttr*)
454 &pPattern->GetItem(ATTR_MERGE);
455 BOOL bMerged = ( pMergeAttr != pDefMerge && *pMergeAttr != *pDefMerge );
456 USHORT nOverlap = ((const ScMergeFlagAttr*) &pPattern->GetItemSet().
457 Get(ATTR_MERGE_FLAG))->GetValue();
458 BOOL bHOverlapped = ((nOverlap & SC_MF_HOR) != 0);
459 BOOL bVOverlapped = ((nOverlap & SC_MF_VER) != 0);
460 BOOL bAutoFilter = ((nOverlap & SC_MF_AUTO) != 0);
461 BOOL bPushButton = ((nOverlap & SC_MF_BUTTON) != 0);
462 BOOL bScenario = ((nOverlap & SC_MF_SCENARIO) != 0);
463 bool bPopupButton = ((nOverlap & SC_MF_BUTTON_POPUP) != 0);
464 bool bFilterActive = ((nOverlap & SC_MF_HIDDEN_MEMBER) != 0);
465 if (bMerged||bHOverlapped||bVOverlapped)
466 bAnyMerged = TRUE; // intern
468 BOOL bHidden, bHideFormula;
469 if (bTabProtect)
471 const ScProtectionAttr& rProtAttr = (const ScProtectionAttr&)
472 pPattern->GetItem(ATTR_PROTECTION);
473 bHidden = rProtAttr.GetHideCell();
474 bHideFormula = rProtAttr.GetHideFormula();
476 else
477 bHidden = bHideFormula = FALSE;
479 ULONG nConditional = ((const SfxUInt32Item&)pPattern->
480 GetItem(ATTR_CONDITIONAL)).GetValue();
481 const ScConditionalFormat* pCondForm = NULL;
482 if ( nConditional && pCondFormList )
483 pCondForm = pCondFormList->GetFormat( nConditional );
487 if ( nArrY==0 || !RowHidden( nCurRow,nTab ) )
489 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
490 if (pBackground != pDefBackground) // Spalten-HG == Standard ?
491 pThisRowInfo->bEmptyBack = FALSE;
492 if (bAutoFilter)
493 pThisRowInfo->bAutoFilter = TRUE;
494 if (bPushButton)
495 pThisRowInfo->bPushButton = TRUE;
497 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
498 pInfo->pBackground = pBackground;
499 pInfo->pPatternAttr = pPattern;
500 pInfo->bMerged = bMerged;
501 pInfo->bHOverlapped = bHOverlapped;
502 pInfo->bVOverlapped = bVOverlapped;
503 pInfo->bAutoFilter = bAutoFilter;
504 pInfo->bPushButton = bPushButton;
505 pInfo->bPopupButton = bPopupButton;
506 pInfo->bFilterActive = bFilterActive;
507 pInfo->pLinesAttr = pLinesAttr;
508 pInfo->mpTLBRLine = pTLBRLine;
509 pInfo->mpBLTRLine = pBLTRLine;
510 pInfo->pShadowAttr = pShadowAttr;
511 // nWidth wird nicht mehr einzeln gesetzt
513 BOOL bEmbed = FALSE; //bIsEmbedded &&
514 nTab >= aEmbedRange.aStart.Tab() &&
515 nTab <= aEmbedRange.aEnd.Tab() &&
516 nX >= aEmbedRange.aStart.Col() &&
517 nX <= aEmbedRange.aEnd.Col() &&
518 nCurRow >= aEmbedRange.aStart.Row() &&
519 nCurRow <= aEmbedRange.aEnd.Row();
521 if (bScenario)
523 pInfo->pBackground = ScGlobal::GetButtonBrushItem();
524 pThisRowInfo->bEmptyBack = FALSE;
526 else if (bEmbed)
528 pInfo->pBackground = ScGlobal::GetEmbeddedBrushItem();
529 pThisRowInfo->bEmptyBack = FALSE;
532 if (bHidden || ( bFormulaMode && bHideFormula && pInfo->pCell
533 && pInfo->pCell->GetCellType()
534 == CELLTYPE_FORMULA ))
535 pInfo->bEmptyCellText = TRUE;
537 if ( pCondForm )
539 String aStyle = pCondForm->GetCellStyle( pInfo->pCell,
540 ScAddress( nX, nCurRow, nTab ) );
541 if (aStyle.Len())
543 SfxStyleSheetBase* pStyleSheet =
544 pStlPool->Find( aStyle, SFX_STYLE_FAMILY_PARA );
545 if ( pStyleSheet )
547 //! Style-Sets cachen !!!
548 pInfo->pConditionSet = &pStyleSheet->GetItemSet();
549 bAnyCondition = TRUE;
551 // if style is not there, treat like no condition
555 ++nArrY;
557 ++nCurRow;
559 while (nCurRow <= nThisRow && nCurRow <= nYExtra);
560 ++nIndex;
562 while ( nIndex < pThisAttrArr->nCount && nThisRow < nYExtra );
565 if (pMarkData && pMarkData->IsMultiMarked())
567 // Blockmarken
568 const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nX;
569 BOOL bThisMarked;
570 nArrY = 1;
571 nCurRow = nY1; // einzelne Zeile
572 nThisRow = nY1; // Ende des Bereichs
574 if ( pThisMarkArr->Search( nY1, nIndex ) )
578 nThisRow=pThisMarkArr->pData[nIndex].nRow; // Ende des Bereichs
579 bThisMarked=pThisMarkArr->pData[nIndex].bMarked;
583 if ( !RowHidden( nCurRow,nTab ) )
585 if ( bThisMarked )
587 BOOL bSkip = bSkipMarks &&
588 nX >= nBlockStartX &&
589 nX <= nBlockEndX &&
590 nCurRow >= nBlockStartY &&
591 nCurRow <= nBlockEndY;
592 if (!bSkip)
594 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
595 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
596 pInfo->bMarked = TRUE;
599 ++nArrY;
601 ++nCurRow;
603 while (nCurRow <= nThisRow && nCurRow <= nY2);
604 ++nIndex;
606 while ( nIndex < pThisMarkArr->nCount && nThisRow < nY2 );
610 else // vordere Spalten
612 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
614 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
615 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
617 pInfo->nWidth = nThisWidth; //! oder nur 0 abfragen ??
622 else
623 pRowInfo[0].pCellInfo[nArrX].nWidth = STD_COL_WIDTH;
624 // STD_COL_WIDTH ganz links und rechts wird fuer DrawExtraShadow gebraucht
627 //-------------------------------------------------------------------------
628 // bedingte Formatierung auswerten
630 if (bAnyCondition)
632 for (nArrY=0; nArrY<nArrCount; nArrY++)
634 for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
636 CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
637 const SfxItemSet* pCondSet = pInfo->pConditionSet;
638 if (pCondSet)
640 const SfxPoolItem* pItem;
642 // Hintergrund
643 if ( pCondSet->GetItemState( ATTR_BACKGROUND, TRUE, &pItem ) == SFX_ITEM_SET )
645 pInfo->pBackground = (const SvxBrushItem*) pItem;
646 pRowInfo[nArrY].bEmptyBack = FALSE;
649 // Umrandung
650 if ( pCondSet->GetItemState( ATTR_BORDER, TRUE, &pItem ) == SFX_ITEM_SET )
651 pInfo->pLinesAttr = (const SvxBoxItem*) pItem;
653 if ( pCondSet->GetItemState( ATTR_BORDER_TLBR, TRUE, &pItem ) == SFX_ITEM_SET )
654 pInfo->mpTLBRLine = static_cast< const SvxLineItem* >( pItem );
655 if ( pCondSet->GetItemState( ATTR_BORDER_BLTR, TRUE, &pItem ) == SFX_ITEM_SET )
656 pInfo->mpBLTRLine = static_cast< const SvxLineItem* >( pItem );
658 // Schatten
659 if ( pCondSet->GetItemState( ATTR_SHADOW, TRUE, &pItem ) == SFX_ITEM_SET )
661 pInfo->pShadowAttr = (const SvxShadowItem*) pItem;
662 bAnyShadow = TRUE;
669 // bedingte Formatierung Ende
670 //-------------------------------------------------------------------------
673 // Daten von zusammengefassten Zellen anpassen
676 if (bAnyMerged)
678 for (nArrY=0; nArrY<nArrCount; nArrY++)
680 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
681 nSignedY = nArrY ? pThisRowInfo->nRowNo : ((SCsROW)nY1)-1;
683 for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
685 SCsCOL nSignedX = ((SCsCOL) nArrX) - 1;
686 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
688 if (pInfo->bMerged || pInfo->bHOverlapped || pInfo->bVOverlapped)
690 SCsCOL nStartX;
691 SCsROW nStartY;
692 SCsCOL nEndX;
693 SCsROW nEndY;
694 lcl_GetMergeRange( nSignedX,nSignedY, nArrY, this,pRowInfo, nX1,nY1,nX2,nY2,nTab,
695 nStartX,nStartY, nEndX,nEndY );
696 const ScPatternAttr* pStartPattern = GetPattern( nStartX,nStartY,nTab );
697 const SfxItemSet* pStartCond = GetCondResult( nStartX,nStartY,nTab );
698 const SfxPoolItem* pItem;
700 // Hintergrund kopieren (oder in output.cxx)
702 if ( !pStartCond || pStartCond->
703 GetItemState(ATTR_BACKGROUND,TRUE,&pItem) != SFX_ITEM_SET )
704 pItem = &pStartPattern->GetItem(ATTR_BACKGROUND);
705 pInfo->pBackground = (const SvxBrushItem*) pItem;
706 pRowInfo[nArrY].bEmptyBack = FALSE;
708 // Schatten
710 if ( !pStartCond || pStartCond->
711 GetItemState(ATTR_SHADOW,TRUE,&pItem) != SFX_ITEM_SET )
712 pItem = &pStartPattern->GetItem(ATTR_SHADOW);
713 pInfo->pShadowAttr = (const SvxShadowItem*) pItem;
714 if (pInfo->pShadowAttr != pDefShadow)
715 bAnyShadow = TRUE;
717 // Blockmarken - wieder mit Original-Merge-Werten
719 BOOL bCellMarked = FALSE;
720 if (bPaintMarks)
721 bCellMarked = ( nStartX >= (SCsCOL) nBlockStartX
722 && nStartX <= (SCsCOL) nBlockEndX
723 && nStartY >= (SCsROW) nBlockStartY
724 && nStartY <= (SCsROW) nBlockEndY );
725 if (pMarkData && pMarkData->IsMultiMarked() && !bCellMarked)
727 const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nStartX;
728 SCSIZE nIndex;
729 if ( pThisMarkArr->Search( nStartY, nIndex ) )
730 bCellMarked=pThisMarkArr->pData[nIndex].bMarked;
733 pInfo->bMarked = bCellMarked;
739 if (bAnyShadow) // Schatten verteilen
741 for (nArrY=0; nArrY<nArrCount; nArrY++)
743 BOOL bTop = ( nArrY == 0 );
744 BOOL bBottom = ( nArrY+1 == nArrCount );
746 for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
748 BOOL bLeft = ( nArrX == nX1 );
749 BOOL bRight = ( nArrX == nX2+2 );
751 CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
752 const SvxShadowItem* pThisAttr = pInfo->pShadowAttr;
753 SvxShadowLocation eLoc = pThisAttr ? pThisAttr->GetLocation() : SVX_SHADOW_NONE;
754 if (eLoc != SVX_SHADOW_NONE)
756 // oder Test auf != eLoc
758 SCsCOL nDxPos = 1;
759 SCsCOL nDxNeg = -1;
761 while ( nArrX+nDxPos < nX2+2 && pRowInfo[0].pCellInfo[nArrX+nDxPos].nWidth == 0 )
762 ++nDxPos;
763 while ( nArrX+nDxNeg > nX1 && pRowInfo[0].pCellInfo[nArrX+nDxNeg].nWidth == 0 )
764 --nDxNeg;
766 BOOL bLeftDiff = !bLeft &&
767 CELLINFO(nDxNeg,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
768 BOOL bRightDiff = !bRight &&
769 CELLINFO(nDxPos,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
770 BOOL bTopDiff = !bTop &&
771 CELLINFO(0,-1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
772 BOOL bBottomDiff = !bBottom &&
773 CELLINFO(0,1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
775 if ( bLayoutRTL )
777 switch (eLoc)
779 case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT; break;
780 case SVX_SHADOW_BOTTOMLEFT: eLoc = SVX_SHADOW_BOTTOMRIGHT; break;
781 case SVX_SHADOW_TOPRIGHT: eLoc = SVX_SHADOW_TOPLEFT; break;
782 case SVX_SHADOW_TOPLEFT: eLoc = SVX_SHADOW_TOPRIGHT; break;
783 default:
785 // added to avoid warnings
790 switch (eLoc)
792 case SVX_SHADOW_BOTTOMRIGHT:
793 if (bBottomDiff)
795 CELLINFO(0,1).pHShadowOrigin = pThisAttr;
796 CELLINFO(0,1).eHShadowPart =
797 bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
799 if (bRightDiff)
801 CELLINFO(1,0).pVShadowOrigin = pThisAttr;
802 CELLINFO(1,0).eVShadowPart =
803 bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
805 if (bBottomDiff && bRightDiff)
807 CELLINFO(1,1).pHShadowOrigin = pThisAttr;
808 CELLINFO(1,1).eHShadowPart = SC_SHADOW_CORNER;
810 break;
812 case SVX_SHADOW_BOTTOMLEFT:
813 if (bBottomDiff)
815 CELLINFO(0,1).pHShadowOrigin = pThisAttr;
816 CELLINFO(0,1).eHShadowPart =
817 bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
819 if (bLeftDiff)
821 CELLINFO(-1,0).pVShadowOrigin = pThisAttr;
822 CELLINFO(-1,0).eVShadowPart =
823 bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
825 if (bBottomDiff && bLeftDiff)
827 CELLINFO(-1,1).pHShadowOrigin = pThisAttr;
828 CELLINFO(-1,1).eHShadowPart = SC_SHADOW_CORNER;
830 break;
832 case SVX_SHADOW_TOPRIGHT:
833 if (bTopDiff)
835 CELLINFO(0,-1).pHShadowOrigin = pThisAttr;
836 CELLINFO(0,-1).eHShadowPart =
837 bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
839 if (bRightDiff)
841 CELLINFO(1,0).pVShadowOrigin = pThisAttr;
842 CELLINFO(1,0).eVShadowPart =
843 bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
845 if (bTopDiff && bRightDiff)
847 CELLINFO(1,-1).pHShadowOrigin = pThisAttr;
848 CELLINFO(1,-1).eHShadowPart = SC_SHADOW_CORNER;
850 break;
852 case SVX_SHADOW_TOPLEFT:
853 if (bTopDiff)
855 CELLINFO(0,-1).pHShadowOrigin = pThisAttr;
856 CELLINFO(0,-1).eHShadowPart =
857 bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
859 if (bLeftDiff)
861 CELLINFO(-1,0).pVShadowOrigin = pThisAttr;
862 CELLINFO(-1,0).eVShadowPart =
863 bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
865 if (bTopDiff && bLeftDiff)
867 CELLINFO(-1,-1).pHShadowOrigin = pThisAttr;
868 CELLINFO(-1,-1).eHShadowPart = SC_SHADOW_CORNER;
870 break;
872 default:
873 DBG_ERROR("falscher Shadow-Enum");
880 rTabInfo.mnArrCount = sal::static_int_cast<USHORT>(nArrCount);
881 rTabInfo.mbPageMode = bPageMode;
883 // ========================================================================
884 // *** create the frame border array ***
886 // RowInfo structs are filled in the range [ 0 , nArrCount-1 ]
887 // each RowInfo contains CellInfo structs in the range [ nX1-1 , nX2+1 ]
889 size_t nColCount = nX2 - nX1 + 3;
890 size_t nRowCount = nArrCount;
892 svx::frame::Array& rArray = rTabInfo.maArray;
893 rArray.Initialize( nColCount, nRowCount );
894 rArray.SetUseDiagDoubleClipping( false );
896 for( size_t nRow = 0; nRow < nRowCount; ++nRow )
898 USHORT nCellInfoY = static_cast< USHORT >( nRow );
899 RowInfo& rThisRowInfo = pRowInfo[ nCellInfoY ];
901 for( size_t nCol = 0; nCol < nColCount; ++nCol )
903 USHORT nCellInfoX = static_cast< USHORT >( nCol + nX1 );
904 const CellInfo& rInfo = rThisRowInfo.pCellInfo[ nCellInfoX ];
906 const SvxBoxItem* pBox = rInfo.pLinesAttr;
907 const SvxLineItem* pTLBR = rInfo.mpTLBRLine;
908 const SvxLineItem* pBLTR = rInfo.mpBLTRLine;
910 size_t nFirstCol = nCol;
911 size_t nFirstRow = nRow;
913 // *** merged cells *** -------------------------------------------
915 if( !rArray.IsMerged( nCol, nRow ) && (rInfo.bMerged || rInfo.bHOverlapped || rInfo.bVOverlapped) )
917 // *** insert merged range in svx::frame::Array ***
919 /* #i69369# top-left cell of a merged range may be located in
920 a hidden column or row. Use lcl_GetMergeRange() to find the
921 complete merged range, then calculate dimensions and
922 document position of the visible range. */
924 // note: document columns are always one less than CellInfoX coords
925 // note: document rows must be looked up in RowInfo structs
927 // current column and row in document coordinates
928 SCCOL nCurrDocCol = static_cast< SCCOL >( nCellInfoX - 1 );
929 SCROW nCurrDocRow = static_cast< SCROW >( (nCellInfoY > 0) ? rThisRowInfo.nRowNo : (nY1 - 1) );
931 // find entire merged range in document, returns signed document coordinates
932 SCsCOL nFirstRealDocColS, nLastRealDocColS;
933 SCsROW nFirstRealDocRowS, nLastRealDocRowS;
934 lcl_GetMergeRange( static_cast< SCsCOL >( nCurrDocCol ), static_cast< SCsROW >( nCurrDocRow ),
935 nCellInfoY, this, pRowInfo, nX1,nY1,nX2,nY2,nTab,
936 nFirstRealDocColS, nFirstRealDocRowS, nLastRealDocColS, nLastRealDocRowS );
938 // *complete* merged range in document coordinates
939 SCCOL nFirstRealDocCol = static_cast< SCCOL >( nFirstRealDocColS );
940 SCROW nFirstRealDocRow = static_cast< SCROW >( nFirstRealDocRowS );
941 SCCOL nLastRealDocCol = static_cast< SCCOL >( nLastRealDocColS );
942 SCROW nLastRealDocRow = static_cast< SCROW >( nLastRealDocRowS );
944 // first visible column (nX1-1 is first processed document column)
945 SCCOL nFirstDocCol = (nX1 > 0) ? ::std::max< SCCOL >( nFirstRealDocCol, nX1 - 1 ) : nFirstRealDocCol;
946 USHORT nFirstCellInfoX = static_cast< USHORT >( nFirstDocCol + 1 );
947 nFirstCol = static_cast< size_t >( nFirstCellInfoX - nX1 );
949 // last visible column (nX2+1 is last processed document column)
950 SCCOL nLastDocCol = (nX2 < MAXCOL) ? ::std::min< SCCOL >( nLastRealDocCol, nX2 + 1 ) : nLastRealDocCol;
951 USHORT nLastCellInfoX = static_cast< USHORT >( nLastDocCol + 1 );
952 size_t nLastCol = static_cast< size_t >( nLastCellInfoX - nX1 );
954 // first visible row
955 USHORT nFirstCellInfoY = nCellInfoY;
956 while( ((nFirstCellInfoY > 1) && (pRowInfo[ nFirstCellInfoY - 1 ].nRowNo >= nFirstRealDocRow)) ||
957 ((nFirstCellInfoY == 1) && (static_cast< SCROW >( nY1 - 1 ) >= nFirstRealDocRow)) )
958 --nFirstCellInfoY;
959 SCROW nFirstDocRow = (nFirstCellInfoY > 0) ? pRowInfo[ nFirstCellInfoY ].nRowNo : static_cast< SCROW >( nY1 - 1 );
960 nFirstRow = static_cast< size_t >( nFirstCellInfoY );
962 // last visible row
963 USHORT nLastCellInfoY = nCellInfoY;
964 while( (sal::static_int_cast<SCSIZE>(nLastCellInfoY + 1) < nArrCount) &&
965 (pRowInfo[ nLastCellInfoY + 1 ].nRowNo <= nLastRealDocRow) )
966 ++nLastCellInfoY;
967 SCROW nLastDocRow = (nLastCellInfoY > 0) ? pRowInfo[ nLastCellInfoY ].nRowNo : static_cast< SCROW >( nY1 - 1 );
968 size_t nLastRow = static_cast< size_t >( nLastCellInfoY );
970 // insert merged range
971 rArray.SetMergedRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
973 // *** find additional size not included in svx::frame::Array ***
975 // additional space before first column
976 if( nFirstCol == 0 )
978 long nSize = 0;
979 for( SCCOL nDocCol = nFirstRealDocCol; nDocCol < nFirstDocCol; ++nDocCol )
980 nSize += std::max( static_cast< long >( GetColWidth( nDocCol, nTab ) * nScaleX ), 1L );
981 rArray.SetAddMergedLeftSize( nCol, nRow, nSize );
983 // additional space after last column
984 if( nLastCol + 1 == nColCount )
986 long nSize = 0;
987 for( SCCOL nDocCol = nLastDocCol + 1; nDocCol <= nLastRealDocCol; ++nDocCol )
988 nSize += std::max( static_cast< long >( GetColWidth( nDocCol, nTab ) * nScaleX ), 1L );
989 rArray.SetAddMergedRightSize( nCol, nRow, nSize );
991 // additional space above first row
992 if( nFirstRow == 0 )
994 long nSize = 0;
995 for( SCROW nDocRow = nFirstRealDocRow; nDocRow < nFirstDocRow; ++nDocRow )
996 nSize += std::max( static_cast< long >( GetRowHeight( nDocRow, nTab ) * nScaleY ), 1L );
997 rArray.SetAddMergedTopSize( nCol, nRow, nSize );
999 // additional space beyond last row
1000 if( nLastRow + 1 == nRowCount )
1002 long nSize = 0;
1003 for( SCROW nDocRow = nLastDocRow + 1; nDocRow <= nLastRealDocRow; ++nDocRow )
1004 nSize += std::max( static_cast< long >( GetRowHeight( nDocRow, nTab ) * nScaleY ), 1L );
1005 rArray.SetAddMergedBottomSize( nCol, nRow, nSize );
1008 // *** use line attributes from real origin cell ***
1010 if( (nFirstRealDocCol != nCurrDocCol) || (nFirstRealDocRow != nCurrDocRow) )
1012 if( const ScPatternAttr* pPattern = GetPattern( nFirstRealDocCol, nFirstRealDocRow, nTab ) )
1014 const SfxItemSet* pCond = GetCondResult( nFirstRealDocCol, nFirstRealDocRow, nTab );
1015 pBox = static_cast< const SvxBoxItem* >( &pPattern->GetItem( ATTR_BORDER, pCond ) );
1016 pTLBR = static_cast< const SvxLineItem* >( &pPattern->GetItem( ATTR_BORDER_TLBR, pCond ) );
1017 pBLTR = static_cast< const SvxLineItem* >( &pPattern->GetItem( ATTR_BORDER_BLTR, pCond ) );
1019 else
1021 pBox = 0;
1022 pTLBR = pBLTR = 0;
1027 // *** borders *** ------------------------------------------------
1029 if( pBox )
1031 rArray.SetCellStyleLeft( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetLeft(), nScaleX ) );
1032 rArray.SetCellStyleRight( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetRight(), nScaleX ) );
1033 rArray.SetCellStyleTop( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetTop(), nScaleY ) );
1034 rArray.SetCellStyleBottom( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetBottom(), nScaleY ) );
1037 if( pTLBR )
1038 rArray.SetCellStyleTLBR( nFirstCol, nFirstRow, svx::frame::Style( pTLBR->GetLine(), nScaleY ) );
1039 if( rInfo.mpBLTRLine )
1040 rArray.SetCellStyleBLTR( nFirstCol, nFirstRow, svx::frame::Style( pBLTR->GetLine(), nScaleY ) );
1044 /* Mirror the entire frame array.
1045 1st param = Mirror the vertical double line styles as well.
1046 2nd param = Do not swap diagonal lines.
1048 if( bLayoutRTL )
1049 rArray.MirrorSelfX( true, false );
1052 // ============================================================================
1054 ScTableInfo::ScTableInfo() :
1055 mpRowInfo( new RowInfo[ ROWINFO_MAX ] ),
1056 mbPageMode( false )
1058 for( USHORT nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx )
1059 mpRowInfo[ nIdx ].pCellInfo = 0;
1062 ScTableInfo::~ScTableInfo()
1064 for( USHORT nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx )
1065 delete [] mpRowInfo[ nIdx ].pCellInfo;
1066 delete [] mpRowInfo;
1069 // ============================================================================