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: fillinfo.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"
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"
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;
73 inline const SvxBorderLine
* GetNullOrLine( const SvxBoxItem
* pBox
, FillInfoLinePos eWhich
)
78 return pBox
->GetTop();
79 else if (eWhich
==FILP_BOTTOM
)
80 return pBox
->GetBottom();
81 else if (eWhich
==FILP_LEFT
)
82 return pBox
->GetLeft();
84 return pBox
->GetRight();
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];
101 BOOL bHOver
= pInfo
->bHOverlapped
;
102 BOOL bVOver
= pInfo
->bVOverlapped
;
104 while (bHOver
) // nY konstant
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
;
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);
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
;
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
->
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
);
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())
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())
226 // zuerst nur die Eintraege fuer die ganze Spalte
229 SCROW nYExtra
= nY2
+1;
230 for (nSignedY
=((SCsROW
)nY1
)-1; nSignedY
<=(SCsROW
)nYExtra
; nSignedY
++)
233 nY
= (SCROW
) nSignedY
;
235 nY
= MAXROW
+1; // ungueltig
239 nDocHeight
= GetRowHeight( nY
, nTab
);
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
);
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
;
262 if (nArrY
>= ROWINFO_MAX
)
264 DBG_ERROR("Zu grosser Bereich bei FillInfo" );
265 nYExtra
= nSignedY
; // Ende
266 nY2
= nYExtra
- 1; // Bereich anpassen
270 if (nSignedY
==(SCsROW
) nYExtra
) // zusaetzliche Zeile verdeckt ?
273 nArrCount
= nArrY
; // incl. Dummys
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
))
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
317 nX
= MAXCOL
+1; // ungueltig
319 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nArrX
];
320 pInfo
->bEmptyCellText
= TRUE
;
323 pInfo
->bMarked
= ( nX
>= nBlockStartX
&& nX
<= nBlockEndX
324 && nY
>= nBlockStartY
&& nY
<= nBlockEndY
);
326 pInfo
->bMarked
= FALSE
;
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
362 if ( (GetColFlags(nX
,nTab
) & CR_HIDDEN
) == 0 ) // Spalte nicht versteckt
364 USHORT nThisWidth
= (USHORT
) (GetColWidth( nX
, nTab
) * nScaleX
);
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
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
);
388 pRowInfo
[0].pCellInfo
[nArrX
].nWidth
= nThisWidth
; //! dies sollte reichen
390 ScColumn
* pThisCol
= &pTab
[nTab
]->aCol
[nX
]; // Spalten-Daten
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
)
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
417 if (nX
+1 >= nX1
) // Attribute/Blockmarken ab nX1-1
419 ScAttrArray
* pThisAttrArr
= pThisCol
->pAttrArray
; // Attribute
422 const ScPatternAttr
* pPattern
;
423 SCROW nCurRow
=nY1
; // einzelne Zeile
425 --nCurRow
; // oben 1 mehr
428 nThisRow
=nCurRow
; // Ende des Bereichs
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
)
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
;
471 const ScProtectionAttr
& rProtAttr
= (const ScProtectionAttr
&)
472 pPattern
->GetItem(ATTR_PROTECTION
);
473 bHidden
= rProtAttr
.GetHideCell();
474 bHideFormula
= rProtAttr
.GetHideFormula();
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
;
493 pThisRowInfo
->bAutoFilter
= TRUE
;
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();
523 pInfo
->pBackground
= ScGlobal::GetButtonBrushItem();
524 pThisRowInfo
->bEmptyBack
= FALSE
;
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
;
539 String aStyle
= pCondForm
->GetCellStyle( pInfo
->pCell
,
540 ScAddress( nX
, nCurRow
, nTab
) );
543 SfxStyleSheetBase
* pStyleSheet
=
544 pStlPool
->Find( aStyle
, SFX_STYLE_FAMILY_PARA
);
547 //! Style-Sets cachen !!!
548 pInfo
->pConditionSet
= &pStyleSheet
->GetItemSet();
549 bAnyCondition
= TRUE
;
551 // if style is not there, treat like no condition
559 while (nCurRow
<= nThisRow
&& nCurRow
<= nYExtra
);
562 while ( nIndex
< pThisAttrArr
->nCount
&& nThisRow
< nYExtra
);
565 if (pMarkData
&& pMarkData
->IsMultiMarked())
568 const ScMarkArray
* pThisMarkArr
= pMarkData
->GetArray()+nX
;
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
) )
587 BOOL bSkip
= bSkipMarks
&&
588 nX
>= nBlockStartX
&&
590 nCurRow
>= nBlockStartY
&&
591 nCurRow
<= nBlockEndY
;
594 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
595 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nArrX
];
596 pInfo
->bMarked
= TRUE
;
603 while (nCurRow
<= nThisRow
&& nCurRow
<= nY2
);
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 ??
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
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
;
640 const SfxPoolItem
* pItem
;
643 if ( pCondSet
->GetItemState( ATTR_BACKGROUND
, TRUE
, &pItem
) == SFX_ITEM_SET
)
645 pInfo
->pBackground
= (const SvxBrushItem
*) pItem
;
646 pRowInfo
[nArrY
].bEmptyBack
= FALSE
;
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
);
659 if ( pCondSet
->GetItemState( ATTR_SHADOW
, TRUE
, &pItem
) == SFX_ITEM_SET
)
661 pInfo
->pShadowAttr
= (const SvxShadowItem
*) pItem
;
669 // bedingte Formatierung Ende
670 //-------------------------------------------------------------------------
673 // Daten von zusammengefassten Zellen anpassen
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
)
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
;
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
)
717 // Blockmarken - wieder mit Original-Merge-Werten
719 BOOL bCellMarked
= FALSE
;
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
;
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
761 while ( nArrX
+nDxPos
< nX2
+2 && pRowInfo
[0].pCellInfo
[nArrX
+nDxPos
].nWidth
== 0 )
763 while ( nArrX
+nDxNeg
> nX1
&& pRowInfo
[0].pCellInfo
[nArrX
+nDxNeg
].nWidth
== 0 )
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
;
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;
785 // added to avoid warnings
792 case SVX_SHADOW_BOTTOMRIGHT
:
795 CELLINFO(0,1).pHShadowOrigin
= pThisAttr
;
796 CELLINFO(0,1).eHShadowPart
=
797 bLeftDiff
? SC_SHADOW_HSTART
: SC_SHADOW_HORIZ
;
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
;
812 case SVX_SHADOW_BOTTOMLEFT
:
815 CELLINFO(0,1).pHShadowOrigin
= pThisAttr
;
816 CELLINFO(0,1).eHShadowPart
=
817 bRightDiff
? SC_SHADOW_HSTART
: SC_SHADOW_HORIZ
;
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
;
832 case SVX_SHADOW_TOPRIGHT
:
835 CELLINFO(0,-1).pHShadowOrigin
= pThisAttr
;
836 CELLINFO(0,-1).eHShadowPart
=
837 bLeftDiff
? SC_SHADOW_HSTART
: SC_SHADOW_HORIZ
;
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
;
852 case SVX_SHADOW_TOPLEFT
:
855 CELLINFO(0,-1).pHShadowOrigin
= pThisAttr
;
856 CELLINFO(0,-1).eHShadowPart
=
857 bRightDiff
? SC_SHADOW_HSTART
: SC_SHADOW_HORIZ
;
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
;
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
);
955 USHORT nFirstCellInfoY
= nCellInfoY
;
956 while( ((nFirstCellInfoY
> 1) && (pRowInfo
[ nFirstCellInfoY
- 1 ].nRowNo
>= nFirstRealDocRow
)) ||
957 ((nFirstCellInfoY
== 1) && (static_cast< SCROW
>( nY1
- 1 ) >= nFirstRealDocRow
)) )
959 SCROW nFirstDocRow
= (nFirstCellInfoY
> 0) ? pRowInfo
[ nFirstCellInfoY
].nRowNo
: static_cast< SCROW
>( nY1
- 1 );
960 nFirstRow
= static_cast< size_t >( nFirstCellInfoY
);
963 USHORT nLastCellInfoY
= nCellInfoY
;
964 while( (sal::static_int_cast
<SCSIZE
>(nLastCellInfoY
+ 1) < nArrCount
) &&
965 (pRowInfo
[ nLastCellInfoY
+ 1 ].nRowNo
<= nLastRealDocRow
) )
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
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
)
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
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
)
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
) );
1027 // *** borders *** ------------------------------------------------
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
) );
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.
1049 rArray
.MirrorSelfX( true, false );
1052 // ============================================================================
1054 ScTableInfo::ScTableInfo() :
1055 mpRowInfo( new RowInfo
[ ROWINFO_MAX
] ),
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 // ============================================================================