re-enabled user-defined numeric fields for dBase export
[LibreOffice.git] / sc / source / core / data / fillinfo.cxx
blob8eb78e64912779bac6dd9d91451f976038e93d69
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4 * This file is part of the LibreOffice project.
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 * This file incorporates work covered by the following license notice:
12 * Licensed to the Apache Software Foundation (ASF) under one or more
13 * contributor license agreements. See the NOTICE file distributed
14 * with this work for additional information regarding copyright
15 * ownership. The ASF licenses this file to you under the Apache
16 * License, Version 2.0 (the "License"); you may not use this file
17 * except in compliance with the License. You may obtain a copy of
18 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "scitems.hxx"
22 #include <editeng/boxitem.hxx>
23 #include <editeng/lineitem.hxx>
24 #include <editeng/editdata.hxx> // can be removed if table has a bLayoutRTL flag
25 #include <editeng/shaditem.hxx>
26 #include <editeng/brushitem.hxx>
28 #include "fillinfo.hxx"
29 #include "document.hxx"
30 #include "formulacell.hxx"
31 #include "table.hxx"
32 #include "attrib.hxx"
33 #include "attarray.hxx"
34 #include "markarr.hxx"
35 #include "markdata.hxx"
36 #include "patattr.hxx"
37 #include "poolhelp.hxx"
38 #include "docpool.hxx"
39 #include "conditio.hxx"
40 #include "colorscale.hxx"
41 #include "stlpool.hxx"
42 #include "cellvalue.hxx"
44 #include <iostream>
46 // -----------------------------------------------------------------------
48 const sal_uInt16 ROWINFO_MAX = 1024;
51 enum FillInfoLinePos
53 FILP_TOP,
54 FILP_BOTTOM,
55 FILP_LEFT,
56 FILP_RIGHT
60 // aehnlich wie in output.cxx
62 static void lcl_GetMergeRange( SCsCOL nX, SCsROW nY, SCSIZE nArrY,
63 ScDocument* pDoc, RowInfo* pRowInfo,
64 SCCOL nX1, SCROW nY1, SCCOL /* nX2 */, SCROW /* nY2 */, SCTAB nTab,
65 SCsCOL& rStartX, SCsROW& rStartY, SCsCOL& rEndX, SCsROW& rEndY )
67 CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1];
69 rStartX = nX;
70 rStartY = nY;
71 bool bHOver = pInfo->bHOverlapped;
72 bool bVOver = pInfo->bVOverlapped;
73 SCCOL nLastCol;
74 SCROW nLastRow;
76 while (bHOver) // nY konstant
78 --rStartX;
79 if (rStartX >= (SCsCOL) nX1 && !pDoc->ColHidden(rStartX, nTab, NULL, &nLastCol))
81 bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped;
82 bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped;
84 else
86 sal_uInt16 nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
87 rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue();
88 bHOver = ((nOverlap & SC_MF_HOR) != 0);
89 bVOver = ((nOverlap & SC_MF_VER) != 0);
93 while (bVOver)
95 --rStartY;
97 if (nArrY>0)
98 --nArrY; // lokale Kopie !
100 if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 &&
101 !pDoc->ColHidden(rStartX, nTab, NULL, &nLastCol) &&
102 !pDoc->RowHidden(rStartY, nTab, NULL, &nLastRow) &&
103 (SCsROW) pRowInfo[nArrY].nRowNo == rStartY)
105 bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped;
107 else
109 sal_uInt16 nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr(
110 rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue();
111 bVOver = ((nOverlap & SC_MF_VER) != 0);
115 const ScMergeAttr* pMerge;
116 if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 &&
117 !pDoc->ColHidden(rStartX, nTab, NULL, &nLastCol) &&
118 !pDoc->RowHidden(rStartY, nTab, NULL, &nLastRow) &&
119 (SCsROW) pRowInfo[nArrY].nRowNo == rStartY)
121 pMerge = (const ScMergeAttr*) &pRowInfo[nArrY].pCellInfo[rStartX+1].pPatternAttr->
122 GetItem(ATTR_MERGE);
124 else
125 pMerge = (const ScMergeAttr*) pDoc->GetAttr(rStartX,rStartY,nTab,ATTR_MERGE);
127 rEndX = rStartX + pMerge->GetColMerge() - 1;
128 rEndY = rStartY + pMerge->GetRowMerge() - 1;
131 #define CELLINFO(x,y) pRowInfo[nArrY+y].pCellInfo[nArrX+x]
133 void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
134 SCTAB nTab, double nScaleX, double nScaleY,
135 bool bPageMode, bool bFormulaMode, const ScMarkData* pMarkData )
137 OSL_ENSURE( maTabs[nTab], "Table does not exist" );
139 bool bLayoutRTL = IsLayoutRTL( nTab );
141 ScDocumentPool* pPool = xPoolHelper->GetDocPool();
142 ScStyleSheetPool* pStlPool = xPoolHelper->GetStylePool();
144 RowInfo* pRowInfo = rTabInfo.mpRowInfo;
146 const SvxBrushItem* pDefBackground =
147 (const SvxBrushItem*) &pPool->GetDefaultItem( ATTR_BACKGROUND );
148 const ScMergeAttr* pDefMerge =
149 (const ScMergeAttr*) &pPool->GetDefaultItem( ATTR_MERGE );
150 const SvxShadowItem* pDefShadow =
151 (const SvxShadowItem*) &pPool->GetDefaultItem( ATTR_SHADOW );
153 SCROW nThisRow;
154 SCCOL nX;
155 SCROW nY;
156 SCsROW nSignedY;
157 SCCOL nArrX;
158 SCSIZE nArrY;
159 SCSIZE nArrCount;
160 bool bAnyMerged = false;
161 bool bAnyShadow = false;
162 bool bAnyCondition = false;
164 bool bTabProtect = IsTabProtected(nTab);
166 // fuer Blockmarken von zusammengefassten Zellen mit
167 // versteckter erster Zeile / Spalte
168 bool bPaintMarks = false;
169 bool bSkipMarks = false;
170 SCCOL nBlockStartX = 0, nBlockEndX = 0;
171 SCROW nBlockEndY = 0, nBlockStartY = 0;
172 if (pMarkData && pMarkData->IsMarked())
174 ScRange aTmpRange;
175 pMarkData->GetMarkArea(aTmpRange);
176 if ( nTab >= aTmpRange.aStart.Tab() && nTab <= aTmpRange.aEnd.Tab() )
178 nBlockStartX = aTmpRange.aStart.Col();
179 nBlockStartY = aTmpRange.aStart.Row();
180 nBlockEndX = aTmpRange.aEnd.Col();
181 nBlockEndY = aTmpRange.aEnd.Row();
182 ExtendHidden( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY, nTab ); //? noetig ?
183 if (pMarkData->IsMarkNegative())
184 bSkipMarks = true;
185 else
186 bPaintMarks = true;
190 // zuerst nur die Eintraege fuer die ganze Spalte
192 nArrY=0;
193 SCROW nYExtra = nY2+1;
194 sal_uInt16 nDocHeight = ScGlobal::nStdRowHeight;
195 SCROW nDocHeightEndRow = -1;
196 for (nSignedY=((SCsROW)nY1)-1; nSignedY<=(SCsROW)nYExtra; nSignedY++)
198 if (nSignedY >= 0)
199 nY = (SCROW) nSignedY;
200 else
201 nY = MAXROW+1; // ungueltig
203 if (nY > nDocHeightEndRow)
205 if (ValidRow(nY))
206 nDocHeight = GetRowHeight( nY, nTab, NULL, &nDocHeightEndRow );
207 else
208 nDocHeight = ScGlobal::nStdRowHeight;
211 if ( nArrY==0 || nDocHeight || nY > MAXROW )
213 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
214 pThisRowInfo->pCellInfo = NULL; // wird unten belegt
216 sal_uInt16 nHeight = (sal_uInt16) ( nDocHeight * nScaleY );
217 if (!nHeight)
218 nHeight = 1;
220 pThisRowInfo->nRowNo = nY; //! Fall < 0 ?
221 pThisRowInfo->nHeight = nHeight;
222 pThisRowInfo->bEmptyBack = true;
223 pThisRowInfo->bEmptyText = true;
224 pThisRowInfo->bChanged = true;
225 pThisRowInfo->bAutoFilter = false;
226 pThisRowInfo->bPivotButton = false;
227 pThisRowInfo->nRotMaxCol = SC_ROTMAX_NONE;
229 ++nArrY;
230 if (nArrY >= ROWINFO_MAX)
232 OSL_FAIL("FillInfo: Range too big" );
233 nYExtra = nSignedY; // Ende
234 nY2 = nYExtra - 1; // Bereich anpassen
237 else
238 if (nSignedY==(SCsROW) nYExtra) // zusaetzliche Zeile verdeckt ?
239 ++nYExtra;
241 nArrCount = nArrY; // incl. Dummys
243 // rotierter Text...
245 // Attribut im Dokument ueberhaupt verwendet?
246 bool bAnyItem = false;
247 sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE );
248 for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++)
249 if (pPool->GetItem2( ATTR_ROTATE_VALUE, nItem ))
251 bAnyItem = true;
252 break;
255 SCCOL nRotMax = nX2;
256 if ( bAnyItem && HasAttrib( 0,nY1,nTab, MAXCOL,nY2+1,nTab,
257 HASATTR_ROTATE | HASATTR_CONDITIONAL ) )
259 //! Conditionals auch bei HASATTR_ROTATE abfragen ????
261 OSL_ENSURE( nArrCount>2, "nArrCount too small" );
262 // FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-2, nX1, nX2 );
263 FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-1, nX1, nX2 );
264 // FindMaxRotCol setzt nRotMaxCol
266 for (nArrY=0; nArrY<nArrCount; nArrY++)
267 if (pRowInfo[nArrY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nArrY].nRotMaxCol > nRotMax)
268 nRotMax = pRowInfo[nArrY].nRotMaxCol;
271 // Zell-Infos erst nach dem Test auf gedrehte allozieren
272 // bis nRotMax wegen nRotateDir Flag
274 for (nArrY=0; nArrY<nArrCount; nArrY++)
276 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
277 nY = pThisRowInfo->nRowNo;
278 pThisRowInfo->pCellInfo = new CellInfo[ nRotMax+1+2 ]; // vom Aufrufer zu loeschen !
280 for (nArrX=0; nArrX<=nRotMax+2; nArrX++) // Zell-Infos vorbelegen
282 if (nArrX>0)
283 nX = nArrX-1;
284 else
285 nX = MAXCOL+1; // ungueltig
287 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
288 pInfo->bEmptyCellText = true;
289 pInfo->maCell.clear();
290 if (bPaintMarks)
291 pInfo->bMarked = ( nX >= nBlockStartX && nX <= nBlockEndX
292 && nY >= nBlockStartY && nY <= nBlockEndY );
293 else
294 pInfo->bMarked = false;
295 pInfo->nWidth = 0;
297 pInfo->nClipMark = SC_CLIPMARK_NONE;
298 pInfo->bMerged = false;
299 pInfo->bHOverlapped = false;
300 pInfo->bVOverlapped = false;
301 pInfo->bAutoFilter = false;
302 pInfo->bPivotButton = false;
303 pInfo->bPivotPopupButton = false;
304 pInfo->bFilterActive = false;
305 pInfo->nRotateDir = SC_ROTDIR_NONE;
307 pInfo->bPrinted = false; // view-intern
308 pInfo->bHideGrid = false; // view-intern
309 pInfo->bEditEngine = false; // view-intern
311 pInfo->pBackground = NULL; //! weglassen?
312 pInfo->pPatternAttr = NULL;
313 pInfo->pConditionSet= NULL;
315 pInfo->pLinesAttr = NULL;
316 pInfo->mpTLBRLine = NULL;
317 pInfo->mpBLTRLine = NULL;
319 pInfo->pShadowAttr = pDefShadow;
320 pInfo->pHShadowOrigin = NULL;
321 pInfo->pVShadowOrigin = NULL;
325 for (nArrX=nX2+3; nArrX<=nRotMax+2; nArrX++) // restliche Breiten eintragen
327 nX = nArrX-1;
328 if ( ValidCol(nX) )
330 if (!ColHidden(nX, nTab))
332 sal_uInt16 nThisWidth = (sal_uInt16) (GetColWidth( nX, nTab ) * nScaleX);
333 if (!nThisWidth)
334 nThisWidth = 1;
336 pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth;
341 ScConditionalFormatList* pCondFormList = GetCondFormList(nTab);
342 if(pCondFormList)
343 pCondFormList->startRendering();
345 for (nArrX=0; nArrX<=nX2+2; nArrX++) // links & rechts + 1
347 nX = (nArrX>0) ? nArrX-1 : MAXCOL+1; // negativ -> ungueltig
349 if ( ValidCol(nX) )
351 // #i58049#, #i57939# Hidden columns must be skipped here, or their attributes
352 // will disturb the output
354 // TODO: Optimize this loop.
355 if (!ColHidden(nX, nTab))
357 sal_uInt16 nThisWidth = (sal_uInt16) (GetColWidth( nX, nTab ) * nScaleX);
358 if (!nThisWidth)
359 nThisWidth = 1;
361 pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth; //! dies sollte reichen
363 ScColumn* pThisCol = &maTabs[nTab]->aCol[nX]; // Spalten-Daten
365 nArrY = 1;
366 SCSIZE nUIndex;
367 bool bHiddenRow = true;
368 SCROW nHiddenEndRow = -1;
369 (void) pThisCol->Search( nY1, nUIndex );
370 while ( nUIndex < pThisCol->maItems.size() &&
371 (nThisRow=pThisCol->maItems[nUIndex].nRow) <= nY2 )
373 if (nThisRow > nHiddenEndRow)
374 bHiddenRow = RowHidden( nThisRow, nTab, NULL, &nHiddenEndRow);
375 if ( !bHiddenRow )
377 while ( pRowInfo[nArrY].nRowNo < nThisRow )
378 ++nArrY;
379 OSL_ENSURE( pRowInfo[nArrY].nRowNo == nThisRow, "FillInfo: Row not found" );
381 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
382 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
383 pInfo->maCell.assign(*pThisCol->maItems[nUIndex].pCell);
384 pThisRowInfo->bEmptyText = false; // Zeile nicht leer
385 pInfo->bEmptyCellText = false; // Zelle nicht leer
386 ++nArrY;
388 ++nUIndex;
391 if (nX+1 >= nX1) // Attribute/Blockmarken ab nX1-1
393 ScAttrArray* pThisAttrArr = pThisCol->pAttrArray; // Attribute
395 nArrY = 0;
396 const ScPatternAttr* pPattern;
397 SCROW nCurRow=nY1; // einzelne Zeile
398 if (nCurRow>0)
399 --nCurRow; // oben 1 mehr
400 else
401 nArrY = 1;
402 nThisRow=nCurRow; // Ende des Bereichs
403 SCSIZE nIndex;
404 (void) pThisAttrArr->Search( nCurRow, nIndex );
409 nThisRow=pThisAttrArr->pData[nIndex].nRow; // Ende des Bereichs
410 pPattern=pThisAttrArr->pData[nIndex].pPattern;
412 const SvxBrushItem* pBackground = (const SvxBrushItem*)
413 &pPattern->GetItem(ATTR_BACKGROUND);
414 const SvxBoxItem* pLinesAttr = (const SvxBoxItem*)
415 &pPattern->GetItem(ATTR_BORDER);
417 const SvxLineItem* pTLBRLine = static_cast< const SvxLineItem* >(
418 &pPattern->GetItem( ATTR_BORDER_TLBR ) );
419 const SvxLineItem* pBLTRLine = static_cast< const SvxLineItem* >(
420 &pPattern->GetItem( ATTR_BORDER_BLTR ) );
422 const SvxShadowItem* pShadowAttr = (const SvxShadowItem*)
423 &pPattern->GetItem(ATTR_SHADOW);
424 if (pShadowAttr != pDefShadow)
425 bAnyShadow = true;
427 const ScMergeAttr* pMergeAttr = (const ScMergeAttr*)
428 &pPattern->GetItem(ATTR_MERGE);
429 bool bMerged = ( pMergeAttr != pDefMerge && *pMergeAttr != *pDefMerge );
430 sal_uInt16 nOverlap = ((const ScMergeFlagAttr*) &pPattern->GetItemSet().
431 Get(ATTR_MERGE_FLAG))->GetValue();
432 bool bHOverlapped = ((nOverlap & SC_MF_HOR) != 0);
433 bool bVOverlapped = ((nOverlap & SC_MF_VER) != 0);
434 bool bAutoFilter = ((nOverlap & SC_MF_AUTO) != 0);
435 bool bPivotButton = ((nOverlap & SC_MF_BUTTON) != 0);
436 bool bScenario = ((nOverlap & SC_MF_SCENARIO) != 0);
437 bool bPivotPopupButton = ((nOverlap & SC_MF_BUTTON_POPUP) != 0);
438 bool bFilterActive = ((nOverlap & SC_MF_HIDDEN_MEMBER) != 0);
439 if (bMerged||bHOverlapped||bVOverlapped)
440 bAnyMerged = true; // intern
442 bool bHidden, bHideFormula;
443 if (bTabProtect)
445 const ScProtectionAttr& rProtAttr = (const ScProtectionAttr&)
446 pPattern->GetItem(ATTR_PROTECTION);
447 bHidden = rProtAttr.GetHideCell();
448 bHideFormula = rProtAttr.GetHideFormula();
450 else
451 bHidden = bHideFormula = false;
453 const std::vector<sal_uInt32>& rCondFormats = static_cast<const ScCondFormatItem&>(pPattern->GetItem(ATTR_CONDITIONAL)).GetCondFormatData();
454 bool bContainsCondFormat = !rCondFormats.empty();
458 SCROW nLastHiddenRow = -1;
459 bool bRowHidden = RowHidden(nCurRow, nTab, NULL, &nLastHiddenRow);
460 if ( nArrY==0 || !bRowHidden )
462 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
463 if (pBackground != pDefBackground) // Spalten-HG == Standard ?
464 pThisRowInfo->bEmptyBack = false;
465 if (bContainsCondFormat)
466 pThisRowInfo->bEmptyBack = false;
467 if (bAutoFilter)
468 pThisRowInfo->bAutoFilter = true;
469 if (bPivotButton || bPivotPopupButton)
470 pThisRowInfo->bPivotButton = true;
472 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
473 pInfo->pBackground = pBackground;
474 pInfo->pPatternAttr = pPattern;
475 pInfo->bMerged = bMerged;
476 pInfo->bHOverlapped = bHOverlapped;
477 pInfo->bVOverlapped = bVOverlapped;
478 pInfo->bAutoFilter = bAutoFilter;
479 pInfo->bPivotButton = bPivotButton;
480 pInfo->bPivotPopupButton = bPivotPopupButton;
481 pInfo->bFilterActive = bFilterActive;
482 pInfo->pLinesAttr = pLinesAttr;
483 pInfo->mpTLBRLine = pTLBRLine;
484 pInfo->mpBLTRLine = pBLTRLine;
485 pInfo->pShadowAttr = pShadowAttr;
486 // nWidth wird nicht mehr einzeln gesetzt
488 if (bScenario)
490 pInfo->pBackground = ScGlobal::GetButtonBrushItem();
491 pThisRowInfo->bEmptyBack = false;
494 if ( bContainsCondFormat )
496 bool bFound = false;
497 for(std::vector<sal_uInt32>::const_iterator itr = rCondFormats.begin();
498 itr != rCondFormats.end() && !bFound; ++itr)
500 ScConditionalFormat* pCondForm = pCondFormList->GetFormat(*itr);
501 if(!pCondForm)
502 continue;
504 ScCondFormatData aData = pCondForm->GetData(
505 pInfo->maCell, ScAddress(nX, nCurRow, nTab));
506 if (!aData.aStyleName.isEmpty())
508 SfxStyleSheetBase* pStyleSheet =
509 pStlPool->Find( aData.aStyleName, SFX_STYLE_FAMILY_PARA );
510 if ( pStyleSheet )
512 //! Style-Sets cachen !!!
513 pInfo->pConditionSet = &pStyleSheet->GetItemSet();
514 bAnyCondition = true;
516 // we need to check already here for protected cells
517 const SfxPoolItem* pItem;
518 if ( bTabProtect && pInfo->pConditionSet->GetItemState( ATTR_PROTECTION, true, &pItem ) == SFX_ITEM_SET )
520 const ScProtectionAttr* pProtAttr = static_cast<const ScProtectionAttr*>(pItem);
521 bHidden = pProtAttr->GetHideCell();
522 bHideFormula = pProtAttr->GetHideFormula();
525 bFound = true;
528 // if style is not there, treat like no condition
530 if(aData.pColorScale)
532 pInfo->pColorScale = aData.pColorScale;
533 bFound = true;
536 if(aData.pDataBar)
538 pInfo->pDataBar = aData.pDataBar;
539 bFound = true;
541 if(aData.pIconSet)
543 pInfo->pIconSet = aData.pIconSet;
544 bFound = true;
549 if (bHidden || (bFormulaMode && bHideFormula && pInfo->maCell.meType == CELLTYPE_FORMULA))
550 pInfo->bEmptyCellText = true;
552 ++nArrY;
554 else if (bRowHidden && nLastHiddenRow >= 0)
556 nCurRow = nLastHiddenRow;
557 if (nCurRow > nThisRow)
558 nCurRow = nThisRow;
560 ++nCurRow;
562 while (nCurRow <= nThisRow && nCurRow <= nYExtra);
563 ++nIndex;
565 while ( nIndex < pThisAttrArr->nCount && nThisRow < nYExtra );
568 if (pMarkData && pMarkData->IsMultiMarked())
570 // Blockmarken
571 const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nX;
572 nArrY = 1;
573 nCurRow = nY1; // einzelne Zeile
574 nThisRow = nY1; // Ende des Bereichs
576 if ( pThisMarkArr->Search( nY1, nIndex ) )
578 bool bThisMarked;
581 nThisRow=pThisMarkArr->pData[nIndex].nRow; // Ende des Bereichs
582 bThisMarked=pThisMarkArr->pData[nIndex].bMarked;
586 if ( !RowHidden( nCurRow,nTab ) )
588 if ( bThisMarked )
590 bool bSkip = bSkipMarks &&
591 nX >= nBlockStartX &&
592 nX <= nBlockEndX &&
593 nCurRow >= nBlockStartY &&
594 nCurRow <= nBlockEndY;
595 if (!bSkip)
597 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
598 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
599 pInfo->bMarked = true;
602 ++nArrY;
604 ++nCurRow;
606 while (nCurRow <= nThisRow && nCurRow <= nY2);
607 ++nIndex;
609 while ( nIndex < pThisMarkArr->nCount && nThisRow < nY2 );
613 else // vordere Spalten
615 for (nArrY=1; nArrY+1<nArrCount; nArrY++)
617 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
618 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
620 pInfo->nWidth = nThisWidth; //! oder nur 0 abfragen ??
625 else
626 pRowInfo[0].pCellInfo[nArrX].nWidth = STD_COL_WIDTH;
627 // STD_COL_WIDTH ganz links und rechts wird fuer DrawExtraShadow gebraucht
630 if(pCondFormList)
631 pCondFormList->endRendering();
632 //-------------------------------------------------------------------------
633 // bedingte Formatierung auswerten
635 if (bAnyCondition)
637 for (nArrY=0; nArrY<nArrCount; nArrY++)
639 for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
641 CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
642 const SfxItemSet* pCondSet = pInfo->pConditionSet;
643 if (pCondSet)
645 const SfxPoolItem* pItem;
647 // Hintergrund
648 if ( pCondSet->GetItemState( ATTR_BACKGROUND, true, &pItem ) == SFX_ITEM_SET )
650 pInfo->pBackground = (const SvxBrushItem*) pItem;
651 pRowInfo[nArrY].bEmptyBack = false;
654 // Umrandung
655 if ( pCondSet->GetItemState( ATTR_BORDER, true, &pItem ) == SFX_ITEM_SET )
656 pInfo->pLinesAttr = (const SvxBoxItem*) pItem;
658 if ( pCondSet->GetItemState( ATTR_BORDER_TLBR, true, &pItem ) == SFX_ITEM_SET )
659 pInfo->mpTLBRLine = static_cast< const SvxLineItem* >( pItem );
660 if ( pCondSet->GetItemState( ATTR_BORDER_BLTR, true, &pItem ) == SFX_ITEM_SET )
661 pInfo->mpBLTRLine = static_cast< const SvxLineItem* >( pItem );
663 // Schatten
664 if ( pCondSet->GetItemState( ATTR_SHADOW, true, &pItem ) == SFX_ITEM_SET )
666 pInfo->pShadowAttr = (const SvxShadowItem*) pItem;
667 bAnyShadow = true;
670 if(pInfo->pColorScale)
672 pRowInfo[nArrY].bEmptyBack = false;
673 pInfo->pBackground = new SvxBrushItem(*pInfo->pColorScale, ATTR_BACKGROUND);
679 // bedingte Formatierung Ende
680 //-------------------------------------------------------------------------
683 // Daten von zusammengefassten Zellen anpassen
686 if (bAnyMerged)
688 for (nArrY=0; nArrY<nArrCount; nArrY++)
690 RowInfo* pThisRowInfo = &pRowInfo[nArrY];
691 nSignedY = nArrY ? pThisRowInfo->nRowNo : ((SCsROW)nY1)-1;
693 for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
695 SCsCOL nSignedX = ((SCsCOL) nArrX) - 1;
696 CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX];
698 if (pInfo->bMerged || pInfo->bHOverlapped || pInfo->bVOverlapped)
700 SCsCOL nStartX;
701 SCsROW nStartY;
702 SCsCOL nEndX;
703 SCsROW nEndY;
704 lcl_GetMergeRange( nSignedX,nSignedY, nArrY, this,pRowInfo, nX1,nY1,nX2,nY2,nTab,
705 nStartX,nStartY, nEndX,nEndY );
706 const ScPatternAttr* pStartPattern = GetPattern( nStartX,nStartY,nTab );
707 const SfxItemSet* pStartCond = GetCondResult( nStartX,nStartY,nTab );
708 const SfxPoolItem* pItem;
710 // Hintergrund kopieren (oder in output.cxx)
712 if ( !pStartCond || pStartCond->
713 GetItemState(ATTR_BACKGROUND,true,&pItem) != SFX_ITEM_SET )
714 pItem = &pStartPattern->GetItem(ATTR_BACKGROUND);
715 pInfo->pBackground = (const SvxBrushItem*) pItem;
716 pRowInfo[nArrY].bEmptyBack = false;
718 // Schatten
720 if ( !pStartCond || pStartCond->
721 GetItemState(ATTR_SHADOW,true,&pItem) != SFX_ITEM_SET )
722 pItem = &pStartPattern->GetItem(ATTR_SHADOW);
723 pInfo->pShadowAttr = (const SvxShadowItem*) pItem;
724 if (pInfo->pShadowAttr != pDefShadow)
725 bAnyShadow = true;
727 // Blockmarken - wieder mit Original-Merge-Werten
729 bool bCellMarked = false;
730 if (bPaintMarks)
731 bCellMarked = ( nStartX >= (SCsCOL) nBlockStartX
732 && nStartX <= (SCsCOL) nBlockEndX
733 && nStartY >= (SCsROW) nBlockStartY
734 && nStartY <= (SCsROW) nBlockEndY );
735 if (pMarkData && pMarkData->IsMultiMarked() && !bCellMarked)
737 const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nStartX;
738 SCSIZE nIndex;
739 if ( pThisMarkArr->Search( nStartY, nIndex ) )
740 bCellMarked=pThisMarkArr->pData[nIndex].bMarked;
743 pInfo->bMarked = bCellMarked;
749 if (bAnyShadow) // Schatten verteilen
751 for (nArrY=0; nArrY<nArrCount; nArrY++)
753 bool bTop = ( nArrY == 0 );
754 bool bBottom = ( nArrY+1 == nArrCount );
756 for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr
758 bool bLeft = ( nArrX == nX1 );
759 bool bRight = ( nArrX == nX2+2 );
761 CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX];
762 const SvxShadowItem* pThisAttr = pInfo->pShadowAttr;
763 SvxShadowLocation eLoc = pThisAttr ? pThisAttr->GetLocation() : SVX_SHADOW_NONE;
764 if (eLoc != SVX_SHADOW_NONE)
766 // oder Test auf != eLoc
768 SCsCOL nDxPos = 1;
769 SCsCOL nDxNeg = -1;
771 while ( nArrX+nDxPos < nX2+2 && pRowInfo[0].pCellInfo[nArrX+nDxPos].nWidth == 0 )
772 ++nDxPos;
773 while ( nArrX+nDxNeg > nX1 && pRowInfo[0].pCellInfo[nArrX+nDxNeg].nWidth == 0 )
774 --nDxNeg;
776 bool bLeftDiff = !bLeft &&
777 CELLINFO(nDxNeg,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
778 bool bRightDiff = !bRight &&
779 CELLINFO(nDxPos,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
780 bool bTopDiff = !bTop &&
781 CELLINFO(0,-1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
782 bool bBottomDiff = !bBottom &&
783 CELLINFO(0,1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE;
785 if ( bLayoutRTL )
787 switch (eLoc)
789 case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT; break;
790 case SVX_SHADOW_BOTTOMLEFT: eLoc = SVX_SHADOW_BOTTOMRIGHT; break;
791 case SVX_SHADOW_TOPRIGHT: eLoc = SVX_SHADOW_TOPLEFT; break;
792 case SVX_SHADOW_TOPLEFT: eLoc = SVX_SHADOW_TOPRIGHT; break;
793 default:
795 // added to avoid warnings
800 switch (eLoc)
802 case SVX_SHADOW_BOTTOMRIGHT:
803 if (bBottomDiff)
805 CELLINFO(0,1).pHShadowOrigin = pThisAttr;
806 CELLINFO(0,1).eHShadowPart =
807 bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
809 if (bRightDiff)
811 CELLINFO(1,0).pVShadowOrigin = pThisAttr;
812 CELLINFO(1,0).eVShadowPart =
813 bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
815 if (bBottomDiff && bRightDiff)
817 CELLINFO(1,1).pHShadowOrigin = pThisAttr;
818 CELLINFO(1,1).eHShadowPart = SC_SHADOW_CORNER;
820 break;
822 case SVX_SHADOW_BOTTOMLEFT:
823 if (bBottomDiff)
825 CELLINFO(0,1).pHShadowOrigin = pThisAttr;
826 CELLINFO(0,1).eHShadowPart =
827 bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
829 if (bLeftDiff)
831 CELLINFO(-1,0).pVShadowOrigin = pThisAttr;
832 CELLINFO(-1,0).eVShadowPart =
833 bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
835 if (bBottomDiff && bLeftDiff)
837 CELLINFO(-1,1).pHShadowOrigin = pThisAttr;
838 CELLINFO(-1,1).eHShadowPart = SC_SHADOW_CORNER;
840 break;
842 case SVX_SHADOW_TOPRIGHT:
843 if (bTopDiff)
845 CELLINFO(0,-1).pHShadowOrigin = pThisAttr;
846 CELLINFO(0,-1).eHShadowPart =
847 bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
849 if (bRightDiff)
851 CELLINFO(1,0).pVShadowOrigin = pThisAttr;
852 CELLINFO(1,0).eVShadowPart =
853 bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
855 if (bTopDiff && bRightDiff)
857 CELLINFO(1,-1).pHShadowOrigin = pThisAttr;
858 CELLINFO(1,-1).eHShadowPart = SC_SHADOW_CORNER;
860 break;
862 case SVX_SHADOW_TOPLEFT:
863 if (bTopDiff)
865 CELLINFO(0,-1).pHShadowOrigin = pThisAttr;
866 CELLINFO(0,-1).eHShadowPart =
867 bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ;
869 if (bLeftDiff)
871 CELLINFO(-1,0).pVShadowOrigin = pThisAttr;
872 CELLINFO(-1,0).eVShadowPart =
873 bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT;
875 if (bTopDiff && bLeftDiff)
877 CELLINFO(-1,-1).pHShadowOrigin = pThisAttr;
878 CELLINFO(-1,-1).eHShadowPart = SC_SHADOW_CORNER;
880 break;
882 default:
883 OSL_FAIL("wrong Shadow-Enum");
890 rTabInfo.mnArrCount = sal::static_int_cast<sal_uInt16>(nArrCount);
891 rTabInfo.mbPageMode = bPageMode;
893 // ========================================================================
894 // *** create the frame border array ***
896 // RowInfo structs are filled in the range [ 0 , nArrCount-1 ]
897 // each RowInfo contains CellInfo structs in the range [ nX1-1 , nX2+1 ]
899 size_t nColCount = nX2 - nX1 + 3;
900 size_t nRowCount = nArrCount;
902 svx::frame::Array& rArray = rTabInfo.maArray;
903 rArray.Initialize( nColCount, nRowCount );
904 rArray.SetUseDiagDoubleClipping( false );
906 for( size_t nRow = 0; nRow < nRowCount; ++nRow )
908 sal_uInt16 nCellInfoY = static_cast< sal_uInt16 >( nRow );
909 RowInfo& rThisRowInfo = pRowInfo[ nCellInfoY ];
911 for( size_t nCol = 0; nCol < nColCount; ++nCol )
913 sal_uInt16 nCellInfoX = static_cast< sal_uInt16 >( nCol + nX1 );
914 const CellInfo& rInfo = rThisRowInfo.pCellInfo[ nCellInfoX ];
916 const SvxBoxItem* pBox = rInfo.pLinesAttr;
917 const SvxLineItem* pTLBR = rInfo.mpTLBRLine;
918 const SvxLineItem* pBLTR = rInfo.mpBLTRLine;
920 size_t nFirstCol = nCol;
921 size_t nFirstRow = nRow;
923 // *** merged cells *** -------------------------------------------
925 if( !rArray.IsMerged( nCol, nRow ) && (rInfo.bMerged || rInfo.bHOverlapped || rInfo.bVOverlapped) )
927 // *** insert merged range in svx::frame::Array ***
929 /* #i69369# top-left cell of a merged range may be located in
930 a hidden column or row. Use lcl_GetMergeRange() to find the
931 complete merged range, then calculate dimensions and
932 document position of the visible range. */
934 // note: document columns are always one less than CellInfoX coords
935 // note: document rows must be looked up in RowInfo structs
937 // current column and row in document coordinates
938 SCCOL nCurrDocCol = static_cast< SCCOL >( nCellInfoX - 1 );
939 SCROW nCurrDocRow = static_cast< SCROW >( (nCellInfoY > 0) ? rThisRowInfo.nRowNo : (nY1 - 1) );
941 // find entire merged range in document, returns signed document coordinates
942 SCsCOL nFirstRealDocColS, nLastRealDocColS;
943 SCsROW nFirstRealDocRowS, nLastRealDocRowS;
944 lcl_GetMergeRange( static_cast< SCsCOL >( nCurrDocCol ), static_cast< SCsROW >( nCurrDocRow ),
945 nCellInfoY, this, pRowInfo, nX1,nY1,nX2,nY2,nTab,
946 nFirstRealDocColS, nFirstRealDocRowS, nLastRealDocColS, nLastRealDocRowS );
948 // *complete* merged range in document coordinates
949 SCCOL nFirstRealDocCol = static_cast< SCCOL >( nFirstRealDocColS );
950 SCROW nFirstRealDocRow = static_cast< SCROW >( nFirstRealDocRowS );
951 SCCOL nLastRealDocCol = static_cast< SCCOL >( nLastRealDocColS );
952 SCROW nLastRealDocRow = static_cast< SCROW >( nLastRealDocRowS );
954 // first visible column (nX1-1 is first processed document column)
955 SCCOL nFirstDocCol = (nX1 > 0) ? ::std::max< SCCOL >( nFirstRealDocCol, nX1 - 1 ) : nFirstRealDocCol;
956 sal_uInt16 nFirstCellInfoX = static_cast< sal_uInt16 >( nFirstDocCol + 1 );
957 nFirstCol = static_cast< size_t >( nFirstCellInfoX - nX1 );
959 // last visible column (nX2+1 is last processed document column)
960 SCCOL nLastDocCol = (nX2 < MAXCOL) ? ::std::min< SCCOL >( nLastRealDocCol, nX2 + 1 ) : nLastRealDocCol;
961 sal_uInt16 nLastCellInfoX = static_cast< sal_uInt16 >( nLastDocCol + 1 );
962 size_t nLastCol = static_cast< size_t >( nLastCellInfoX - nX1 );
964 // first visible row
965 sal_uInt16 nFirstCellInfoY = nCellInfoY;
966 while( ((nFirstCellInfoY > 1) && (pRowInfo[ nFirstCellInfoY - 1 ].nRowNo >= nFirstRealDocRow)) ||
967 ((nFirstCellInfoY == 1) && (static_cast< SCROW >( nY1 - 1 ) >= nFirstRealDocRow)) )
968 --nFirstCellInfoY;
969 SCROW nFirstDocRow = (nFirstCellInfoY > 0) ? pRowInfo[ nFirstCellInfoY ].nRowNo : static_cast< SCROW >( nY1 - 1 );
970 nFirstRow = static_cast< size_t >( nFirstCellInfoY );
972 // last visible row
973 sal_uInt16 nLastCellInfoY = nCellInfoY;
974 while( (sal::static_int_cast<SCSIZE>(nLastCellInfoY + 1) < nArrCount) &&
975 (pRowInfo[ nLastCellInfoY + 1 ].nRowNo <= nLastRealDocRow) )
976 ++nLastCellInfoY;
977 SCROW nLastDocRow = (nLastCellInfoY > 0) ? pRowInfo[ nLastCellInfoY ].nRowNo : static_cast< SCROW >( nY1 - 1 );
978 size_t nLastRow = static_cast< size_t >( nLastCellInfoY );
980 // insert merged range
981 rArray.SetMergedRange( nFirstCol, nFirstRow, nLastCol, nLastRow );
983 // *** find additional size not included in svx::frame::Array ***
985 // additional space before first column
986 if( nFirstCol == 0 )
988 long nSize = 0;
989 for( SCCOL nDocCol = nFirstRealDocCol; nDocCol < nFirstDocCol; ++nDocCol )
990 nSize += std::max( static_cast< long >( GetColWidth( nDocCol, nTab ) * nScaleX ), 1L );
991 rArray.SetAddMergedLeftSize( nCol, nRow, nSize );
993 // additional space after last column
994 if( nLastCol + 1 == nColCount )
996 long nSize = 0;
997 for( SCCOL nDocCol = nLastDocCol + 1; nDocCol <= nLastRealDocCol; ++nDocCol )
998 nSize += std::max( static_cast< long >( GetColWidth( nDocCol, nTab ) * nScaleX ), 1L );
999 rArray.SetAddMergedRightSize( nCol, nRow, nSize );
1001 // additional space above first row
1002 if( nFirstRow == 0 )
1004 long nSize = 0;
1005 for( SCROW nDocRow = nFirstRealDocRow; nDocRow < nFirstDocRow; ++nDocRow )
1006 nSize += std::max( static_cast< long >( GetRowHeight( nDocRow, nTab ) * nScaleY ), 1L );
1007 rArray.SetAddMergedTopSize( nCol, nRow, nSize );
1009 // additional space beyond last row
1010 if( nLastRow + 1 == nRowCount )
1012 long nSize = 0;
1013 for( SCROW nDocRow = nLastDocRow + 1; nDocRow <= nLastRealDocRow; ++nDocRow )
1014 nSize += std::max( static_cast< long >( GetRowHeight( nDocRow, nTab ) * nScaleY ), 1L );
1015 rArray.SetAddMergedBottomSize( nCol, nRow, nSize );
1018 // *** use line attributes from real origin cell ***
1020 if( (nFirstRealDocCol != nCurrDocCol) || (nFirstRealDocRow != nCurrDocRow) )
1022 if( const ScPatternAttr* pPattern = GetPattern( nFirstRealDocCol, nFirstRealDocRow, nTab ) )
1024 const SfxItemSet* pCond = GetCondResult( nFirstRealDocCol, nFirstRealDocRow, nTab );
1025 pBox = static_cast< const SvxBoxItem* >( &pPattern->GetItem( ATTR_BORDER, pCond ) );
1026 pTLBR = static_cast< const SvxLineItem* >( &pPattern->GetItem( ATTR_BORDER_TLBR, pCond ) );
1027 pBLTR = static_cast< const SvxLineItem* >( &pPattern->GetItem( ATTR_BORDER_BLTR, pCond ) );
1029 else
1031 pBox = 0;
1032 pTLBR = pBLTR = 0;
1037 // *** borders *** ------------------------------------------------
1039 if( pBox )
1041 rArray.SetCellStyleLeft( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetLeft(), nScaleX ) );
1042 rArray.SetCellStyleRight( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetRight(), nScaleX ) );
1043 rArray.SetCellStyleTop( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetTop(), nScaleY ) );
1044 rArray.SetCellStyleBottom( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetBottom(), nScaleY ) );
1047 if( pTLBR )
1048 rArray.SetCellStyleTLBR( nFirstCol, nFirstRow, svx::frame::Style( pTLBR->GetLine(), nScaleY ) );
1049 if( rInfo.mpBLTRLine )
1050 rArray.SetCellStyleBLTR( nFirstCol, nFirstRow, svx::frame::Style( pBLTR->GetLine(), nScaleY ) );
1054 /* Mirror the entire frame array.
1055 1st param = Mirror the vertical double line styles as well.
1056 2nd param = Do not swap diagonal lines.
1058 if( bLayoutRTL )
1059 rArray.MirrorSelfX( true, false );
1062 // ============================================================================
1064 ScTableInfo::ScTableInfo() :
1065 mpRowInfo( new RowInfo[ ROWINFO_MAX ] ),
1066 mbPageMode( false )
1068 for( sal_uInt16 nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx )
1069 mpRowInfo[ nIdx ].pCellInfo = 0;
1072 ScTableInfo::~ScTableInfo()
1074 for( sal_uInt16 nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx )
1075 delete [] mpRowInfo[ nIdx ].pCellInfo;
1076 delete [] mpRowInfo;
1079 // ============================================================================
1081 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */