update ooo310-m15
[ooovba.git] / sc / source / core / data / fillinfo.cxx
blobf8814019624d8ebeb0c9357b67391a791db947eb
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"
58 // -----------------------------------------------------------------------
60 const USHORT ROWINFO_MAX = 1024;
63 enum FillInfoLinePos
65 FILP_TOP,
66 FILP_BOTTOM,
67 FILP_LEFT,
68 FILP_RIGHT
72 inline const SvxBorderLine* GetNullOrLine( const SvxBoxItem* pBox, FillInfoLinePos eWhich )
74 if (pBox)
76 if (eWhich==FILP_TOP)
77 return pBox->GetTop();
78 else if (eWhich==FILP_BOTTOM)
79 return pBox->GetBottom();
80 else if (eWhich==FILP_LEFT)
81 return pBox->GetLeft();
82 else
83 return pBox->GetRight();
85 else
86 return NULL;
89 // aehnlich wie in output.cxx
91 void lcl_GetMergeRange( SCsCOL nX, SCsROW nY, SCSIZE nArrY,
92 ScDocument* pDoc, RowInfo* pRowInfo,
93 SCCOL nX1, SCROW nY1, SCCOL /* nX2 */, SCROW /* nY2 */, SCTAB nTab,
94 SCsCOL& rStartX, SCsROW& rStartY, SCsCOL& rEndX, SCsROW& rEndY )
96 CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1];
98 rStartX = nX;
99 rStartY = nY;
100 BOOL bHOver = pInfo->bHOverlapped;
101 BOOL bVOver = pInfo->bVOverlapped;
102 SCCOL nLastCol;
103 SCROW nLastRow;
105 while (bHOver) // nY konstant
107 --rStartX;
108 if (rStartX >= (SCsCOL) nX1 && !pDoc->ColHidden(rStartX, nTab, nLastCol))
110 bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped;
111 bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped;
113 else
115 USHORT nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
116 rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue();
117 bHOver = ((nOverlap & SC_MF_HOR) != 0);
118 bVOver = ((nOverlap & SC_MF_VER) != 0);
122 while (bVOver)
124 --rStartY;
126 if (nArrY>0)
127 --nArrY; // lokale Kopie !
129 if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 &&
130 !pDoc->ColHidden(rStartX, nTab, nLastCol) &&
131 !pDoc->RowHidden(rStartY, nTab, nLastRow) &&
132 (SCsROW) pRowInfo[nArrY].nRowNo == rStartY)
134 bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped;
135 bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped;
137 else
139 USHORT nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
140 rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue();
141 bHOver = ((nOverlap & SC_MF_HOR) != 0);
142 bVOver = ((nOverlap & SC_MF_VER) != 0);
146 const ScMergeAttr* pMerge;
147 if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 &&
148 !pDoc->ColHidden(rStartX, nTab, nLastCol) &&
149 !pDoc->RowHidden(rStartY, nTab, nLastRow) &&
150 (SCsROW) pRowInfo[nArrY].nRowNo == rStartY)
152 pMerge = (const ScMergeAttr*) &pRowInfo[nArrY].pCellInfo[rStartX+1].pPatternAttr->
153 GetItem(ATTR_MERGE);
155 else
156 pMerge = (const ScMergeAttr*) pDoc->GetAttr(rStartX,rStartY,nTab,ATTR_MERGE);
158 rEndX = rStartX + pMerge->GetColMerge() - 1;
159 rEndY = rStartY + pMerge->GetRowMerge() - 1;
162 #define CELLINFO(x,y) pRowInfo[nArrY+y].pCellInfo[nArrX+x]
164 void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
165 SCTAB nTab, double nScaleX, double nScaleY,
166 BOOL bPageMode, BOOL bFormulaMode, const ScMarkData* pMarkData )
168 DBG_ASSERT( pTab[nTab], "Tabelle existiert nicht" );
170 BOOL bLayoutRTL = IsLayoutRTL( nTab );
172 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
173 ScStyleSheetPool* pStlPool = xPoolHelper->GetStylePool();
175 RowInfo* pRowInfo = rTabInfo.mpRowInfo;
177 const SvxBrushItem* pDefBackground =
178 (const SvxBrushItem*) &pPool->GetDefaultItem( ATTR_BACKGROUND );
179 const ScMergeAttr* pDefMerge =
180 (const ScMergeAttr*) &pPool->GetDefaultItem( ATTR_MERGE );
181 const SvxShadowItem* pDefShadow =
182 (const SvxShadowItem*) &pPool->GetDefaultItem( ATTR_SHADOW );
184 SCROW nThisRow;
185 SCCOL nX;
186 SCROW nY;
187 SCsROW nSignedY;
188 SCCOL nArrX;
189 SCSIZE nArrY;
190 SCSIZE nArrCount;
191 BOOL bAnyMerged = FALSE;
192 BOOL bAnyShadow = FALSE;
193 BOOL bAnyCondition = FALSE;
195 BOOL bTabProtect = IsTabProtected(nTab);
197 // fuer Blockmarken von zusammengefassten Zellen mit
198 // versteckter erster Zeile / Spalte
199 BOOL bPaintMarks = FALSE;
200 BOOL bSkipMarks = FALSE;
201 SCCOL nBlockStartX = 0, nBlockEndX = 0;
202 SCROW nBlockEndY = 0, nBlockStartY = 0;
203 if (pMarkData && pMarkData->IsMarked())
205 ScRange aTmpRange;
206 pMarkData->GetMarkArea(aTmpRange);
207 if ( nTab >= aTmpRange.aStart.Tab() && nTab <= aTmpRange.aEnd.Tab() )
209 nBlockStartX = aTmpRange.aStart.Col();
210 nBlockStartY = aTmpRange.aStart.Row();
211 nBlockEndX = aTmpRange.aEnd.Col();
212 nBlockEndY = aTmpRange.aEnd.Row();
213 ExtendHidden( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY, nTab ); //? noetig ?
214 if (pMarkData->IsMarkNegative())
215 bSkipMarks = TRUE;
216 else
217 bPaintMarks = TRUE;
221 // zuerst nur die Eintraege fuer die ganze Spalte
223 nArrY=0;
224 SCROW nYExtra = nY2+1;
225 for (nSignedY=((SCsROW)nY1)-1; nSignedY<=(SCsROW)nYExtra; nSignedY++)
227 if (nSignedY >= 0)
228 nY = (SCROW) nSignedY;
229 else
230 nY = MAXROW+1; // ungueltig
232 USHORT nDocHeight;
233 if (ValidRow(nY))
234 nDocHeight = GetRowHeight( nY, nTab );
235 else
236 nDocHeight = ScGlobal::nStdRowHeight;
238 if ( nArrY==0 || nDocHeight || nY > MAXROW )
240 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
241 pThisRowInfo->pCellInfo = NULL; // wird unten belegt
243 USHORT nHeight = (USHORT) ( nDocHeight * nScaleY );
244 if (!nHeight)
245 nHeight = 1;
247 pThisRowInfo->nRowNo = nY; //! Fall < 0 ?
248 pThisRowInfo->nHeight = nHeight;
249 pThisRowInfo->bEmptyBack = TRUE;
250 pThisRowInfo->bEmptyText = TRUE;
251 pThisRowInfo->bChanged = TRUE;
252 pThisRowInfo->bAutoFilter = FALSE;
253 pThisRowInfo->bPushButton = FALSE;
254 pThisRowInfo->nRotMaxCol = SC_ROTMAX_NONE;
256 ++nArrY;
257 if (nArrY >= ROWINFO_MAX)
259 DBG_ERROR("Zu grosser Bereich bei FillInfo" );
260 nYExtra = nSignedY; // Ende
261 nY2 = nYExtra - 1; // Bereich anpassen
264 else
265 if (nSignedY==(SCsROW) nYExtra) // zusaetzliche Zeile verdeckt ?
266 ++nYExtra;
268 nArrCount = nArrY; // incl. Dummys
270 // rotierter Text...
272 // Attribut im Dokument ueberhaupt verwendet?
273 BOOL bAnyItem = FALSE;
274 USHORT nRotCount = pPool->GetItemCount( ATTR_ROTATE_VALUE );
275 for (USHORT nItem=0; nItem<nRotCount; nItem++)
276 if (pPool->GetItem( ATTR_ROTATE_VALUE, nItem ))
278 bAnyItem = TRUE;
279 break;
282 SCCOL nRotMax = nX2;
283 if ( bAnyItem && HasAttrib( 0,nY1,nTab, MAXCOL,nY2+1,nTab,
284 HASATTR_ROTATE | HASATTR_CONDITIONAL ) )
286 //! Conditionals auch bei HASATTR_ROTATE abfragen ????
288 DBG_ASSERT( nArrCount>2, "nArrCount zu klein" );
289 // FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-2, nX1, nX2 );
290 FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-1, nX1, nX2 );
291 // FindMaxRotCol setzt nRotMaxCol
293 for (nArrY=0; nArrY<nArrCount; nArrY++)
294 if (pRowInfo[nArrY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nArrY].nRotMaxCol > nRotMax)
295 nRotMax = pRowInfo[nArrY].nRotMaxCol;
298 // Zell-Infos erst nach dem Test auf gedrehte allozieren
299 // bis nRotMax wegen nRotateDir Flag
301 for (nArrY=0; nArrY<nArrCount; nArrY++)
303 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
304 nY = pThisRowInfo->nRowNo;
305 pThisRowInfo->pCellInfo = new CellInfo[ nRotMax+1+2 ]; // vom Aufrufer zu loeschen !
307 for (nArrX=0; nArrX<=nRotMax+2; nArrX++) // Zell-Infos vorbelegen
309 if (nArrX>0)
310 nX = nArrX-1;
311 else
312 nX = MAXCOL+1; // ungueltig
314 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
315 pInfo->bEmptyCellText = TRUE;
316 pInfo->pCell = NULL;
317 if (bPaintMarks)
318 pInfo->bMarked = ( nX >= nBlockStartX && nX <= nBlockEndX
319 && nY >= nBlockStartY && nY <= nBlockEndY );
320 else
321 pInfo->bMarked = FALSE;
322 pInfo->nWidth = 0;
324 pInfo->nClipMark = SC_CLIPMARK_NONE;
325 pInfo->bMerged = FALSE;
326 pInfo->bHOverlapped = FALSE;
327 pInfo->bVOverlapped = FALSE;
328 pInfo->bAutoFilter = FALSE;
329 pInfo->bPushButton = FALSE;
330 pInfo->bPopupButton = false;
331 pInfo->bFilterActive = false;
332 pInfo->nRotateDir = SC_ROTDIR_NONE;
334 pInfo->bPrinted = FALSE; // view-intern
335 pInfo->bHideGrid = FALSE; // view-intern
336 pInfo->bEditEngine = FALSE; // view-intern
338 pInfo->pBackground = NULL; //! weglassen?
339 pInfo->pPatternAttr = NULL;
340 pInfo->pConditionSet= NULL;
342 pInfo->pLinesAttr = NULL;
343 pInfo->mpTLBRLine = NULL;
344 pInfo->mpBLTRLine = NULL;
346 pInfo->pShadowAttr = pDefShadow;
347 pInfo->pHShadowOrigin = NULL;
348 pInfo->pVShadowOrigin = NULL;
352 for (nArrX=nX2+3; nArrX<=nRotMax+2; nArrX++) // restliche Breiten eintragen
354 nX = nArrX-1;
355 if ( ValidCol(nX) )
357 if (!ColHidden(nX, nTab))
359 USHORT nThisWidth = (USHORT) (GetColWidth( nX, nTab ) * nScaleX);
360 if (!nThisWidth)
361 nThisWidth = 1;
363 pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth;
368 for (nArrX=0; nArrX<=nX2+2; nArrX++) // links & rechts + 1
370 nX = (nArrX>0) ? nArrX-1 : MAXCOL+1; // negativ -> ungueltig
372 if ( ValidCol(nX) )
374 // #i58049#, #i57939# Hidden columns must be skipped here, or their attributes
375 // will disturb the output
377 // TODO: Optimize this loop.
378 if (!ColHidden(nX, nTab))
380 USHORT nThisWidth = (USHORT) (GetColWidth( nX, nTab ) * nScaleX);
381 if (!nThisWidth)
382 nThisWidth = 1;
384 pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth; //! dies sollte reichen
386 ScColumn* pThisCol = &pTab[nTab]->aCol[nX]; // Spalten-Daten
388 nArrY = 1;
389 SCSIZE nUIndex;
390 (void) pThisCol->Search( nY1, nUIndex );
391 while ( nUIndex < pThisCol->nCount &&
392 (nThisRow=pThisCol->pItems[nUIndex].nRow) <= nY2 )
394 if ( !RowHidden( nThisRow,nTab ) )
396 while ( pRowInfo[nArrY].nRowNo < nThisRow )
397 ++nArrY;
398 DBG_ASSERT( pRowInfo[nArrY].nRowNo == nThisRow, "Zeile nicht gefunden in FillInfo" );
400 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
401 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
402 pInfo->pCell = pThisCol->pItems[nUIndex].pCell;
403 if (pInfo->pCell->GetCellType() != CELLTYPE_NOTE)
405 pThisRowInfo->bEmptyText = FALSE; // Zeile nicht leer
406 pInfo->bEmptyCellText = FALSE; // Zelle nicht leer
408 ++nArrY;
410 ++nUIndex;
413 if (nX+1 >= nX1) // Attribute/Blockmarken ab nX1-1
415 ScAttrArray* pThisAttrArr = pThisCol->pAttrArray; // Attribute
417 nArrY = 0;
418 const ScPatternAttr* pPattern;
419 SCROW nCurRow=nY1; // einzelne Zeile
420 if (nCurRow>0)
421 --nCurRow; // oben 1 mehr
422 else
423 nArrY = 1;
424 nThisRow=nCurRow; // Ende des Bereichs
425 SCSIZE nIndex;
426 (void) pThisAttrArr->Search( nCurRow, nIndex );
431 nThisRow=pThisAttrArr->pData[nIndex].nRow; // Ende des Bereichs
432 pPattern=pThisAttrArr->pData[nIndex].pPattern;
434 const SvxBrushItem* pBackground = (const SvxBrushItem*)
435 &pPattern->GetItem(ATTR_BACKGROUND);
436 const SvxBoxItem* pLinesAttr = (const SvxBoxItem*)
437 &pPattern->GetItem(ATTR_BORDER);
439 const SvxLineItem* pTLBRLine = static_cast< const SvxLineItem* >(
440 &pPattern->GetItem( ATTR_BORDER_TLBR ) );
441 const SvxLineItem* pBLTRLine = static_cast< const SvxLineItem* >(
442 &pPattern->GetItem( ATTR_BORDER_BLTR ) );
444 const SvxShadowItem* pShadowAttr = (const SvxShadowItem*)
445 &pPattern->GetItem(ATTR_SHADOW);
446 if (pShadowAttr != pDefShadow)
447 bAnyShadow = TRUE;
449 const ScMergeAttr* pMergeAttr = (const ScMergeAttr*)
450 &pPattern->GetItem(ATTR_MERGE);
451 BOOL bMerged = ( pMergeAttr != pDefMerge && *pMergeAttr != *pDefMerge );
452 USHORT nOverlap = ((const ScMergeFlagAttr*) &pPattern->GetItemSet().
453 Get(ATTR_MERGE_FLAG))->GetValue();
454 BOOL bHOverlapped = ((nOverlap & SC_MF_HOR) != 0);
455 BOOL bVOverlapped = ((nOverlap & SC_MF_VER) != 0);
456 BOOL bAutoFilter = ((nOverlap & SC_MF_AUTO) != 0);
457 BOOL bPushButton = ((nOverlap & SC_MF_BUTTON) != 0);
458 BOOL bScenario = ((nOverlap & SC_MF_SCENARIO) != 0);
459 bool bPopupButton = ((nOverlap & SC_MF_BUTTON_POPUP) != 0);
460 bool bFilterActive = ((nOverlap & SC_MF_HIDDEN_MEMBER) != 0);
461 if (bMerged||bHOverlapped||bVOverlapped)
462 bAnyMerged = TRUE; // intern
464 BOOL bHidden, bHideFormula;
465 if (bTabProtect)
467 const ScProtectionAttr& rProtAttr = (const ScProtectionAttr&)
468 pPattern->GetItem(ATTR_PROTECTION);
469 bHidden = rProtAttr.GetHideCell();
470 bHideFormula = rProtAttr.GetHideFormula();
472 else
473 bHidden = bHideFormula = FALSE;
475 ULONG nConditional = ((const SfxUInt32Item&)pPattern->
476 GetItem(ATTR_CONDITIONAL)).GetValue();
477 const ScConditionalFormat* pCondForm = NULL;
478 if ( nConditional && pCondFormList )
479 pCondForm = pCondFormList->GetFormat( nConditional );
483 #define NEW_METHOD 1
484 #if NEW_METHOD
485 SCROW nLastHiddenRow = -1;
486 bool bRowHidden = RowHidden(nCurRow, nTab, nLastHiddenRow);
487 #else
488 bool bRowHidden = RowHidden(nCurRow, nTab);
489 #endif
490 if ( nArrY==0 || !bRowHidden )
492 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
493 if (pBackground != pDefBackground) // Spalten-HG == Standard ?
494 pThisRowInfo->bEmptyBack = FALSE;
495 if (bAutoFilter)
496 pThisRowInfo->bAutoFilter = TRUE;
497 if (bPushButton)
498 pThisRowInfo->bPushButton = TRUE;
500 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
501 pInfo->pBackground = pBackground;
502 pInfo->pPatternAttr = pPattern;
503 pInfo->bMerged = bMerged;
504 pInfo->bHOverlapped = bHOverlapped;
505 pInfo->bVOverlapped = bVOverlapped;
506 pInfo->bAutoFilter = bAutoFilter;
507 pInfo->bPushButton = bPushButton;
508 pInfo->bPopupButton = bPopupButton;
509 pInfo->bFilterActive = bFilterActive;
510 pInfo->pLinesAttr = pLinesAttr;
511 pInfo->mpTLBRLine = pTLBRLine;
512 pInfo->mpBLTRLine = pBLTRLine;
513 pInfo->pShadowAttr = pShadowAttr;
514 // nWidth wird nicht mehr einzeln gesetzt
516 BOOL bEmbed = FALSE; //bIsEmbedded &&
517 nTab >= aEmbedRange.aStart.Tab() &&
518 nTab <= aEmbedRange.aEnd.Tab() &&
519 nX >= aEmbedRange.aStart.Col() &&
520 nX <= aEmbedRange.aEnd.Col() &&
521 nCurRow >= aEmbedRange.aStart.Row() &&
522 nCurRow <= aEmbedRange.aEnd.Row();
524 if (bScenario)
526 pInfo->pBackground = ScGlobal::GetButtonBrushItem();
527 pThisRowInfo->bEmptyBack = FALSE;
529 else if (bEmbed)
531 pInfo->pBackground = ScGlobal::GetEmbeddedBrushItem();
532 pThisRowInfo->bEmptyBack = FALSE;
535 if (bHidden || ( bFormulaMode && bHideFormula && pInfo->pCell
536 && pInfo->pCell->GetCellType()
537 == CELLTYPE_FORMULA ))
538 pInfo->bEmptyCellText = TRUE;
540 if ( pCondForm )
542 String aStyle = pCondForm->GetCellStyle( pInfo->pCell,
543 ScAddress( nX, nCurRow, nTab ) );
544 if (aStyle.Len())
546 SfxStyleSheetBase* pStyleSheet =
547 pStlPool->Find( aStyle, SFX_STYLE_FAMILY_PARA );
548 if ( pStyleSheet )
550 //! Style-Sets cachen !!!
551 pInfo->pConditionSet = &pStyleSheet->GetItemSet();
552 bAnyCondition = TRUE;
554 // if style is not there, treat like no condition
558 ++nArrY;
560 #if NEW_METHOD
561 else if (bRowHidden && nLastHiddenRow >= 0)
563 nCurRow = nLastHiddenRow;
564 if (nCurRow > nThisRow)
565 nCurRow = nThisRow;
567 #endif
568 ++nCurRow;
570 while (nCurRow <= nThisRow && nCurRow <= nYExtra);
571 ++nIndex;
573 while ( nIndex < pThisAttrArr->nCount && nThisRow < nYExtra );
576 if (pMarkData && pMarkData->IsMultiMarked())
578 // Blockmarken
579 const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nX;
580 BOOL bThisMarked;
581 nArrY = 1;
582 nCurRow = nY1; // einzelne Zeile
583 nThisRow = nY1; // Ende des Bereichs
585 if ( pThisMarkArr->Search( nY1, nIndex ) )
589 nThisRow=pThisMarkArr->pData[nIndex].nRow; // Ende des Bereichs
590 bThisMarked=pThisMarkArr->pData[nIndex].bMarked;
594 if ( !RowHidden( nCurRow,nTab ) )
596 if ( bThisMarked )
598 BOOL bSkip = bSkipMarks &&
599 nX >= nBlockStartX &&
600 nX <= nBlockEndX &&
601 nCurRow >= nBlockStartY &&
602 nCurRow <= nBlockEndY;
603 if (!bSkip)
605 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
606 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
607 pInfo->bMarked = TRUE;
610 ++nArrY;
612 ++nCurRow;
614 while (nCurRow <= nThisRow && nCurRow <= nY2);
615 ++nIndex;
617 while ( nIndex < pThisMarkArr->nCount && nThisRow < nY2 );
621 else // vordere Spalten
623 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
625 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
626 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
628 pInfo->nWidth = nThisWidth; //! oder nur 0 abfragen ??
633 else
634 pRowInfo[0].pCellInfo[nArrX].nWidth = STD_COL_WIDTH;
635 // STD_COL_WIDTH ganz links und rechts wird fuer DrawExtraShadow gebraucht
638 //-------------------------------------------------------------------------
639 // bedingte Formatierung auswerten
641 if (bAnyCondition)
643 for (nArrY=0; nArrY<nArrCount; nArrY++)
645 for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
647 CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
648 const SfxItemSet* pCondSet = pInfo->pConditionSet;
649 if (pCondSet)
651 const SfxPoolItem* pItem;
653 // Hintergrund
654 if ( pCondSet->GetItemState( ATTR_BACKGROUND, TRUE, &pItem ) == SFX_ITEM_SET )
656 pInfo->pBackground = (const SvxBrushItem*) pItem;
657 pRowInfo[nArrY].bEmptyBack = FALSE;
660 // Umrandung
661 if ( pCondSet->GetItemState( ATTR_BORDER, TRUE, &pItem ) == SFX_ITEM_SET )
662 pInfo->pLinesAttr = (const SvxBoxItem*) pItem;
664 if ( pCondSet->GetItemState( ATTR_BORDER_TLBR, TRUE, &pItem ) == SFX_ITEM_SET )
665 pInfo->mpTLBRLine = static_cast< const SvxLineItem* >( pItem );
666 if ( pCondSet->GetItemState( ATTR_BORDER_BLTR, TRUE, &pItem ) == SFX_ITEM_SET )
667 pInfo->mpBLTRLine = static_cast< const SvxLineItem* >( pItem );
669 // Schatten
670 if ( pCondSet->GetItemState( ATTR_SHADOW, TRUE, &pItem ) == SFX_ITEM_SET )
672 pInfo->pShadowAttr = (const SvxShadowItem*) pItem;
673 bAnyShadow = TRUE;
680 // bedingte Formatierung Ende
681 //-------------------------------------------------------------------------
684 // Daten von zusammengefassten Zellen anpassen
687 if (bAnyMerged)
689 for (nArrY=0; nArrY<nArrCount; nArrY++)
691 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
692 nSignedY = nArrY ? pThisRowInfo->nRowNo : ((SCsROW)nY1)-1;
694 for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
696 SCsCOL nSignedX = ((SCsCOL) nArrX) - 1;
697 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
699 if (pInfo->bMerged || pInfo->bHOverlapped || pInfo->bVOverlapped)
701 SCsCOL nStartX;
702 SCsROW nStartY;
703 SCsCOL nEndX;
704 SCsROW nEndY;
705 lcl_GetMergeRange( nSignedX,nSignedY, nArrY, this,pRowInfo, nX1,nY1,nX2,nY2,nTab,
706 nStartX,nStartY, nEndX,nEndY );
707 const ScPatternAttr* pStartPattern = GetPattern( nStartX,nStartY,nTab );
708 const SfxItemSet* pStartCond = GetCondResult( nStartX,nStartY,nTab );
709 const SfxPoolItem* pItem;
711 // Hintergrund kopieren (oder in output.cxx)
713 if ( !pStartCond || pStartCond->
714 GetItemState(ATTR_BACKGROUND,TRUE,&pItem) != SFX_ITEM_SET )
715 pItem = &pStartPattern->GetItem(ATTR_BACKGROUND);
716 pInfo->pBackground = (const SvxBrushItem*) pItem;
717 pRowInfo[nArrY].bEmptyBack = FALSE;
719 // Schatten
721 if ( !pStartCond || pStartCond->
722 GetItemState(ATTR_SHADOW,TRUE,&pItem) != SFX_ITEM_SET )
723 pItem = &pStartPattern->GetItem(ATTR_SHADOW);
724 pInfo->pShadowAttr = (const SvxShadowItem*) pItem;
725 if (pInfo->pShadowAttr != pDefShadow)
726 bAnyShadow = TRUE;
728 // Blockmarken - wieder mit Original-Merge-Werten
730 BOOL bCellMarked = FALSE;
731 if (bPaintMarks)
732 bCellMarked = ( nStartX >= (SCsCOL) nBlockStartX
733 && nStartX <= (SCsCOL) nBlockEndX
734 && nStartY >= (SCsROW) nBlockStartY
735 && nStartY <= (SCsROW) nBlockEndY );
736 if (pMarkData && pMarkData->IsMultiMarked() && !bCellMarked)
738 const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nStartX;
739 SCSIZE nIndex;
740 if ( pThisMarkArr->Search( nStartY, nIndex ) )
741 bCellMarked=pThisMarkArr->pData[nIndex].bMarked;
744 pInfo->bMarked = bCellMarked;
750 if (bAnyShadow) // Schatten verteilen
752 for (nArrY=0; nArrY<nArrCount; nArrY++)
754 BOOL bTop = ( nArrY == 0 );
755 BOOL bBottom = ( nArrY+1 == nArrCount );
757 for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
759 BOOL bLeft = ( nArrX == nX1 );
760 BOOL bRight = ( nArrX == nX2+2 );
762 CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
763 const SvxShadowItem* pThisAttr = pInfo->pShadowAttr;
764 SvxShadowLocation eLoc = pThisAttr ? pThisAttr->GetLocation() : SVX_SHADOW_NONE;
765 if (eLoc != SVX_SHADOW_NONE)
767 // oder Test auf != eLoc
769 SCsCOL nDxPos = 1;
770 SCsCOL nDxNeg = -1;
772 while ( nArrX+nDxPos < nX2+2 && pRowInfo[0].pCellInfo[nArrX+nDxPos].nWidth == 0 )
773 ++nDxPos;
774 while ( nArrX+nDxNeg > nX1 && pRowInfo[0].pCellInfo[nArrX+nDxNeg].nWidth == 0 )
775 --nDxNeg;
777 BOOL bLeftDiff = !bLeft &&
778 CELLINFO(nDxNeg,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
779 BOOL bRightDiff = !bRight &&
780 CELLINFO(nDxPos,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
781 BOOL bTopDiff = !bTop &&
782 CELLINFO(0,-1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
783 BOOL bBottomDiff = !bBottom &&
784 CELLINFO(0,1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
786 if ( bLayoutRTL )
788 switch (eLoc)
790 case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT; break;
791 case SVX_SHADOW_BOTTOMLEFT: eLoc = SVX_SHADOW_BOTTOMRIGHT; break;
792 case SVX_SHADOW_TOPRIGHT: eLoc = SVX_SHADOW_TOPLEFT; break;
793 case SVX_SHADOW_TOPLEFT: eLoc = SVX_SHADOW_TOPRIGHT; break;
794 default:
796 // added to avoid warnings
801 switch (eLoc)
803 case SVX_SHADOW_BOTTOMRIGHT:
804 if (bBottomDiff)
806 CELLINFO(0,1).pHShadowOrigin = pThisAttr;
807 CELLINFO(0,1).eHShadowPart =
808 bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
810 if (bRightDiff)
812 CELLINFO(1,0).pVShadowOrigin = pThisAttr;
813 CELLINFO(1,0).eVShadowPart =
814 bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
816 if (bBottomDiff && bRightDiff)
818 CELLINFO(1,1).pHShadowOrigin = pThisAttr;
819 CELLINFO(1,1).eHShadowPart = SC_SHADOW_CORNER;
821 break;
823 case SVX_SHADOW_BOTTOMLEFT:
824 if (bBottomDiff)
826 CELLINFO(0,1).pHShadowOrigin = pThisAttr;
827 CELLINFO(0,1).eHShadowPart =
828 bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
830 if (bLeftDiff)
832 CELLINFO(-1,0).pVShadowOrigin = pThisAttr;
833 CELLINFO(-1,0).eVShadowPart =
834 bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
836 if (bBottomDiff && bLeftDiff)
838 CELLINFO(-1,1).pHShadowOrigin = pThisAttr;
839 CELLINFO(-1,1).eHShadowPart = SC_SHADOW_CORNER;
841 break;
843 case SVX_SHADOW_TOPRIGHT:
844 if (bTopDiff)
846 CELLINFO(0,-1).pHShadowOrigin = pThisAttr;
847 CELLINFO(0,-1).eHShadowPart =
848 bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
850 if (bRightDiff)
852 CELLINFO(1,0).pVShadowOrigin = pThisAttr;
853 CELLINFO(1,0).eVShadowPart =
854 bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
856 if (bTopDiff && bRightDiff)
858 CELLINFO(1,-1).pHShadowOrigin = pThisAttr;
859 CELLINFO(1,-1).eHShadowPart = SC_SHADOW_CORNER;
861 break;
863 case SVX_SHADOW_TOPLEFT:
864 if (bTopDiff)
866 CELLINFO(0,-1).pHShadowOrigin = pThisAttr;
867 CELLINFO(0,-1).eHShadowPart =
868 bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
870 if (bLeftDiff)
872 CELLINFO(-1,0).pVShadowOrigin = pThisAttr;
873 CELLINFO(-1,0).eVShadowPart =
874 bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
876 if (bTopDiff && bLeftDiff)
878 CELLINFO(-1,-1).pHShadowOrigin = pThisAttr;
879 CELLINFO(-1,-1).eHShadowPart = SC_SHADOW_CORNER;
881 break;
883 default:
884 DBG_ERROR("falscher Shadow-Enum");
891 rTabInfo.mnArrCount = sal::static_int_cast<USHORT>(nArrCount);
892 rTabInfo.mbPageMode = bPageMode;
894 // ========================================================================
895 // *** create the frame border array ***
897 // RowInfo structs are filled in the range [ 0 , nArrCount-1 ]
898 // each RowInfo contains CellInfo structs in the range [ nX1-1 , nX2+1 ]
900 size_t nColCount = nX2 - nX1 + 3;
901 size_t nRowCount = nArrCount;
903 svx::frame::Array& rArray = rTabInfo.maArray;
904 rArray.Initialize( nColCount, nRowCount );
905 rArray.SetUseDiagDoubleClipping( false );
907 for( size_t nRow = 0; nRow < nRowCount; ++nRow )
909 USHORT nCellInfoY = static_cast< USHORT >( nRow );
910 RowInfo& rThisRowInfo = pRowInfo[ nCellInfoY ];
912 for( size_t nCol = 0; nCol < nColCount; ++nCol )
914 USHORT nCellInfoX = static_cast< USHORT >( nCol + nX1 );
915 const CellInfo& rInfo = rThisRowInfo.pCellInfo[ nCellInfoX ];
917 const SvxBoxItem* pBox = rInfo.pLinesAttr;
918 const SvxLineItem* pTLBR = rInfo.mpTLBRLine;
919 const SvxLineItem* pBLTR = rInfo.mpBLTRLine;
921 size_t nFirstCol = nCol;
922 size_t nFirstRow = nRow;
924 // *** merged cells *** -------------------------------------------
926 if( !rArray.IsMerged( nCol, nRow ) && (rInfo.bMerged || rInfo.bHOverlapped || rInfo.bVOverlapped) )
928 // *** insert merged range in svx::frame::Array ***
930 /* #i69369# top-left cell of a merged range may be located in
931 a hidden column or row. Use lcl_GetMergeRange() to find the
932 complete merged range, then calculate dimensions and
933 document position of the visible range. */
935 // note: document columns are always one less than CellInfoX coords
936 // note: document rows must be looked up in RowInfo structs
938 // current column and row in document coordinates
939 SCCOL nCurrDocCol = static_cast< SCCOL >( nCellInfoX - 1 );
940 SCROW nCurrDocRow = static_cast< SCROW >( (nCellInfoY > 0) ? rThisRowInfo.nRowNo : (nY1 - 1) );
942 // find entire merged range in document, returns signed document coordinates
943 SCsCOL nFirstRealDocColS, nLastRealDocColS;
944 SCsROW nFirstRealDocRowS, nLastRealDocRowS;
945 lcl_GetMergeRange( static_cast< SCsCOL >( nCurrDocCol ), static_cast< SCsROW >( nCurrDocRow ),
946 nCellInfoY, this, pRowInfo, nX1,nY1,nX2,nY2,nTab,
947 nFirstRealDocColS, nFirstRealDocRowS, nLastRealDocColS, nLastRealDocRowS );
949 // *complete* merged range in document coordinates
950 SCCOL nFirstRealDocCol = static_cast< SCCOL >( nFirstRealDocColS );
951 SCROW nFirstRealDocRow = static_cast< SCROW >( nFirstRealDocRowS );
952 SCCOL nLastRealDocCol = static_cast< SCCOL >( nLastRealDocColS );
953 SCROW nLastRealDocRow = static_cast< SCROW >( nLastRealDocRowS );
955 // first visible column (nX1-1 is first processed document column)
956 SCCOL nFirstDocCol = (nX1 > 0) ? ::std::max< SCCOL >( nFirstRealDocCol, nX1 - 1 ) : nFirstRealDocCol;
957 USHORT nFirstCellInfoX = static_cast< USHORT >( nFirstDocCol + 1 );
958 nFirstCol = static_cast< size_t >( nFirstCellInfoX - nX1 );
960 // last visible column (nX2+1 is last processed document column)
961 SCCOL nLastDocCol = (nX2 < MAXCOL) ? ::std::min< SCCOL >( nLastRealDocCol, nX2 + 1 ) : nLastRealDocCol;
962 USHORT nLastCellInfoX = static_cast< USHORT >( nLastDocCol + 1 );
963 size_t nLastCol = static_cast< size_t >( nLastCellInfoX - nX1 );
965 // first visible row
966 USHORT nFirstCellInfoY = nCellInfoY;
967 while( ((nFirstCellInfoY > 1) && (pRowInfo[ nFirstCellInfoY - 1 ].nRowNo >= nFirstRealDocRow)) ||
968 ((nFirstCellInfoY == 1) && (static_cast< SCROW >( nY1 - 1 ) >= nFirstRealDocRow)) )
969 --nFirstCellInfoY;
970 SCROW nFirstDocRow = (nFirstCellInfoY > 0) ? pRowInfo[ nFirstCellInfoY ].nRowNo : static_cast< SCROW >( nY1 - 1 );
971 nFirstRow = static_cast< size_t >( nFirstCellInfoY );
973 // last visible row
974 USHORT nLastCellInfoY = nCellInfoY;
975 while( (sal::static_int_cast<SCSIZE>(nLastCellInfoY + 1) < nArrCount) &&
976 (pRowInfo[ nLastCellInfoY + 1 ].nRowNo <= nLastRealDocRow) )
977 ++nLastCellInfoY;
978 SCROW nLastDocRow = (nLastCellInfoY > 0) ? pRowInfo[ nLastCellInfoY ].nRowNo : static_cast< SCROW >( nY1 - 1 );
979 size_t nLastRow = static_cast< size_t >( nLastCellInfoY );
981 // insert merged range
982 rArray.SetMergedRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
984 // *** find additional size not included in svx::frame::Array ***
986 // additional space before first column
987 if( nFirstCol == 0 )
989 long nSize = 0;
990 for( SCCOL nDocCol = nFirstRealDocCol; nDocCol < nFirstDocCol; ++nDocCol )
991 nSize += std::max( static_cast< long >( GetColWidth( nDocCol, nTab ) * nScaleX ), 1L );
992 rArray.SetAddMergedLeftSize( nCol, nRow, nSize );
994 // additional space after last column
995 if( nLastCol + 1 == nColCount )
997 long nSize = 0;
998 for( SCCOL nDocCol = nLastDocCol + 1; nDocCol <= nLastRealDocCol; ++nDocCol )
999 nSize += std::max( static_cast< long >( GetColWidth( nDocCol, nTab ) * nScaleX ), 1L );
1000 rArray.SetAddMergedRightSize( nCol, nRow, nSize );
1002 // additional space above first row
1003 if( nFirstRow == 0 )
1005 long nSize = 0;
1006 for( SCROW nDocRow = nFirstRealDocRow; nDocRow < nFirstDocRow; ++nDocRow )
1007 nSize += std::max( static_cast< long >( GetRowHeight( nDocRow, nTab ) * nScaleY ), 1L );
1008 rArray.SetAddMergedTopSize( nCol, nRow, nSize );
1010 // additional space beyond last row
1011 if( nLastRow + 1 == nRowCount )
1013 long nSize = 0;
1014 for( SCROW nDocRow = nLastDocRow + 1; nDocRow <= nLastRealDocRow; ++nDocRow )
1015 nSize += std::max( static_cast< long >( GetRowHeight( nDocRow, nTab ) * nScaleY ), 1L );
1016 rArray.SetAddMergedBottomSize( nCol, nRow, nSize );
1019 // *** use line attributes from real origin cell ***
1021 if( (nFirstRealDocCol != nCurrDocCol) || (nFirstRealDocRow != nCurrDocRow) )
1023 if( const ScPatternAttr* pPattern = GetPattern( nFirstRealDocCol, nFirstRealDocRow, nTab ) )
1025 const SfxItemSet* pCond = GetCondResult( nFirstRealDocCol, nFirstRealDocRow, nTab );
1026 pBox = static_cast< const SvxBoxItem* >( &pPattern->GetItem( ATTR_BORDER, pCond ) );
1027 pTLBR = static_cast< const SvxLineItem* >( &pPattern->GetItem( ATTR_BORDER_TLBR, pCond ) );
1028 pBLTR = static_cast< const SvxLineItem* >( &pPattern->GetItem( ATTR_BORDER_BLTR, pCond ) );
1030 else
1032 pBox = 0;
1033 pTLBR = pBLTR = 0;
1038 // *** borders *** ------------------------------------------------
1040 if( pBox )
1042 rArray.SetCellStyleLeft( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetLeft(), nScaleX ) );
1043 rArray.SetCellStyleRight( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetRight(), nScaleX ) );
1044 rArray.SetCellStyleTop( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetTop(), nScaleY ) );
1045 rArray.SetCellStyleBottom( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetBottom(), nScaleY ) );
1048 if( pTLBR )
1049 rArray.SetCellStyleTLBR( nFirstCol, nFirstRow, svx::frame::Style( pTLBR->GetLine(), nScaleY ) );
1050 if( rInfo.mpBLTRLine )
1051 rArray.SetCellStyleBLTR( nFirstCol, nFirstRow, svx::frame::Style( pBLTR->GetLine(), nScaleY ) );
1055 /* Mirror the entire frame array.
1056 1st param = Mirror the vertical double line styles as well.
1057 2nd param = Do not swap diagonal lines.
1059 if( bLayoutRTL )
1060 rArray.MirrorSelfX( true, false );
1063 // ============================================================================
1065 ScTableInfo::ScTableInfo() :
1066 mpRowInfo( new RowInfo[ ROWINFO_MAX ] ),
1067 mbPageMode( false )
1069 for( USHORT nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx )
1070 mpRowInfo[ nIdx ].pCellInfo = 0;
1073 ScTableInfo::~ScTableInfo()
1075 for( USHORT nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx )
1076 delete [] mpRowInfo[ nIdx ].pCellInfo;
1077 delete [] mpRowInfo;
1080 // ============================================================================