diff options
Diffstat (limited to 'sc/source/core/data/fillinfo.cxx')
-rw-r--r-- | sc/source/core/data/fillinfo.cxx | 1081 |
1 files changed, 1081 insertions, 0 deletions
diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx new file mode 100644 index 000000000000..0bd0da8c1e74 --- /dev/null +++ b/sc/source/core/data/fillinfo.cxx @@ -0,0 +1,1081 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/boxitem.hxx> +#include <editeng/bolnitem.hxx> +#include <editeng/editdata.hxx> // can be removed if table has a bLayoutRTL flag +#include <editeng/shaditem.hxx> + +#include "fillinfo.hxx" +#include "document.hxx" +#include "cell.hxx" +#include "table.hxx" +#include "attrib.hxx" +#include "attarray.hxx" +#include "markarr.hxx" +#include "markdata.hxx" +#include "patattr.hxx" +#include "poolhelp.hxx" +#include "docpool.hxx" +#include "conditio.hxx" +#include "stlpool.hxx" + +// ----------------------------------------------------------------------- + +const USHORT ROWINFO_MAX = 1024; + + +enum FillInfoLinePos + { + FILP_TOP, + FILP_BOTTOM, + FILP_LEFT, + FILP_RIGHT + }; + + +inline const SvxBorderLine* GetNullOrLine( const SvxBoxItem* pBox, FillInfoLinePos eWhich ) +{ + if (pBox) + { + if (eWhich==FILP_TOP) + return pBox->GetTop(); + else if (eWhich==FILP_BOTTOM) + return pBox->GetBottom(); + else if (eWhich==FILP_LEFT) + return pBox->GetLeft(); + else + return pBox->GetRight(); + } + else + return NULL; +} + +// aehnlich wie in output.cxx + +void lcl_GetMergeRange( SCsCOL nX, SCsROW nY, SCSIZE nArrY, + ScDocument* pDoc, RowInfo* pRowInfo, + SCCOL nX1, SCROW nY1, SCCOL /* nX2 */, SCROW /* nY2 */, SCTAB nTab, + SCsCOL& rStartX, SCsROW& rStartY, SCsCOL& rEndX, SCsROW& rEndY ) +{ + CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1]; + + rStartX = nX; + rStartY = nY; + BOOL bHOver = pInfo->bHOverlapped; + BOOL bVOver = pInfo->bVOverlapped; + SCCOL nLastCol; + SCROW nLastRow; + + while (bHOver) // nY konstant + { + --rStartX; + if (rStartX >= (SCsCOL) nX1 && !pDoc->ColHidden(rStartX, nTab, nLastCol)) + { + bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped; + bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped; + } + else + { + USHORT nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr( + rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue(); + bHOver = ((nOverlap & SC_MF_HOR) != 0); + bVOver = ((nOverlap & SC_MF_VER) != 0); + } + } + + while (bVOver) + { + --rStartY; + + if (nArrY>0) + --nArrY; // lokale Kopie ! + + if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 && + !pDoc->ColHidden(rStartX, nTab, nLastCol) && + !pDoc->RowHidden(rStartY, nTab, nLastRow) && + (SCsROW) pRowInfo[nArrY].nRowNo == rStartY) + { + bHOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bHOverlapped; + bVOver = pRowInfo[nArrY].pCellInfo[rStartX+1].bVOverlapped; + } + else + { + USHORT nOverlap = ((ScMergeFlagAttr*)pDoc->GetAttr( + rStartX, rStartY, nTab, ATTR_MERGE_FLAG ))->GetValue(); + bHOver = ((nOverlap & SC_MF_HOR) != 0); + bVOver = ((nOverlap & SC_MF_VER) != 0); + } + } + + const ScMergeAttr* pMerge; + if (rStartX >= (SCsCOL) nX1 && rStartY >= (SCsROW) nY1 && + !pDoc->ColHidden(rStartX, nTab, nLastCol) && + !pDoc->RowHidden(rStartY, nTab, nLastRow) && + (SCsROW) pRowInfo[nArrY].nRowNo == rStartY) + { + pMerge = (const ScMergeAttr*) &pRowInfo[nArrY].pCellInfo[rStartX+1].pPatternAttr-> + GetItem(ATTR_MERGE); + } + else + pMerge = (const ScMergeAttr*) pDoc->GetAttr(rStartX,rStartY,nTab,ATTR_MERGE); + + rEndX = rStartX + pMerge->GetColMerge() - 1; + rEndY = rStartY + pMerge->GetRowMerge() - 1; +} + +#define CELLINFO(x,y) pRowInfo[nArrY+y].pCellInfo[nArrX+x] + +void ScDocument::FillInfo( ScTableInfo& rTabInfo, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, + SCTAB nTab, double nScaleX, double nScaleY, + BOOL bPageMode, BOOL bFormulaMode, const ScMarkData* pMarkData ) +{ + DBG_ASSERT( pTab[nTab], "Tabelle existiert nicht" ); + + BOOL bLayoutRTL = IsLayoutRTL( nTab ); + + ScDocumentPool* pPool = xPoolHelper->GetDocPool(); + ScStyleSheetPool* pStlPool = xPoolHelper->GetStylePool(); + + RowInfo* pRowInfo = rTabInfo.mpRowInfo; + + const SvxBrushItem* pDefBackground = + (const SvxBrushItem*) &pPool->GetDefaultItem( ATTR_BACKGROUND ); + const ScMergeAttr* pDefMerge = + (const ScMergeAttr*) &pPool->GetDefaultItem( ATTR_MERGE ); + const SvxShadowItem* pDefShadow = + (const SvxShadowItem*) &pPool->GetDefaultItem( ATTR_SHADOW ); + + SCROW nThisRow; + SCCOL nX; + SCROW nY; + SCsROW nSignedY; + SCCOL nArrX; + SCSIZE nArrY; + SCSIZE nArrCount; + BOOL bAnyMerged = FALSE; + BOOL bAnyShadow = FALSE; + BOOL bAnyCondition = FALSE; + + BOOL bTabProtect = IsTabProtected(nTab); + + // fuer Blockmarken von zusammengefassten Zellen mit + // versteckter erster Zeile / Spalte + BOOL bPaintMarks = FALSE; + BOOL bSkipMarks = FALSE; + SCCOL nBlockStartX = 0, nBlockEndX = 0; + SCROW nBlockEndY = 0, nBlockStartY = 0; + if (pMarkData && pMarkData->IsMarked()) + { + ScRange aTmpRange; + pMarkData->GetMarkArea(aTmpRange); + if ( nTab >= aTmpRange.aStart.Tab() && nTab <= aTmpRange.aEnd.Tab() ) + { + nBlockStartX = aTmpRange.aStart.Col(); + nBlockStartY = aTmpRange.aStart.Row(); + nBlockEndX = aTmpRange.aEnd.Col(); + nBlockEndY = aTmpRange.aEnd.Row(); + ExtendHidden( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY, nTab ); //? noetig ? + if (pMarkData->IsMarkNegative()) + bSkipMarks = TRUE; + else + bPaintMarks = TRUE; + } + } + + // zuerst nur die Eintraege fuer die ganze Spalte + + nArrY=0; + SCROW nYExtra = nY2+1; + USHORT nDocHeight = ScGlobal::nStdRowHeight; + SCROW nDocHeightEndRow = -1; + for (nSignedY=((SCsROW)nY1)-1; nSignedY<=(SCsROW)nYExtra; nSignedY++) + { + if (nSignedY >= 0) + nY = (SCROW) nSignedY; + else + nY = MAXROW+1; // ungueltig + + if (nY > nDocHeightEndRow) + { + if (ValidRow(nY)) + nDocHeight = GetRowHeight( nY, nTab, NULL, &nDocHeightEndRow ); + else + nDocHeight = ScGlobal::nStdRowHeight; + } + + if ( nArrY==0 || nDocHeight || nY > MAXROW ) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + pThisRowInfo->pCellInfo = NULL; // wird unten belegt + + USHORT nHeight = (USHORT) ( nDocHeight * nScaleY ); + if (!nHeight) + nHeight = 1; + + pThisRowInfo->nRowNo = nY; //! Fall < 0 ? + pThisRowInfo->nHeight = nHeight; + pThisRowInfo->bEmptyBack = TRUE; + pThisRowInfo->bEmptyText = TRUE; + pThisRowInfo->bChanged = TRUE; + pThisRowInfo->bAutoFilter = FALSE; + pThisRowInfo->bPushButton = FALSE; + pThisRowInfo->nRotMaxCol = SC_ROTMAX_NONE; + + ++nArrY; + if (nArrY >= ROWINFO_MAX) + { + DBG_ERROR("Zu grosser Bereich bei FillInfo" ); + nYExtra = nSignedY; // Ende + nY2 = nYExtra - 1; // Bereich anpassen + } + } + else + if (nSignedY==(SCsROW) nYExtra) // zusaetzliche Zeile verdeckt ? + ++nYExtra; + } + nArrCount = nArrY; // incl. Dummys + + // rotierter Text... + + // Attribut im Dokument ueberhaupt verwendet? + BOOL bAnyItem = FALSE; + USHORT nRotCount = pPool->GetItemCount( ATTR_ROTATE_VALUE ); + for (USHORT nItem=0; nItem<nRotCount; nItem++) + if (pPool->GetItem( ATTR_ROTATE_VALUE, nItem )) + { + bAnyItem = TRUE; + break; + } + + SCCOL nRotMax = nX2; + if ( bAnyItem && HasAttrib( 0,nY1,nTab, MAXCOL,nY2+1,nTab, + HASATTR_ROTATE | HASATTR_CONDITIONAL ) ) + { + //! Conditionals auch bei HASATTR_ROTATE abfragen ???? + + DBG_ASSERT( nArrCount>2, "nArrCount zu klein" ); +// FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-2, nX1, nX2 ); + FindMaxRotCol( nTab, &pRowInfo[1], nArrCount-1, nX1, nX2 ); + // FindMaxRotCol setzt nRotMaxCol + + for (nArrY=0; nArrY<nArrCount; nArrY++) + if (pRowInfo[nArrY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nArrY].nRotMaxCol > nRotMax) + nRotMax = pRowInfo[nArrY].nRotMaxCol; + } + + // Zell-Infos erst nach dem Test auf gedrehte allozieren + // bis nRotMax wegen nRotateDir Flag + + for (nArrY=0; nArrY<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + nY = pThisRowInfo->nRowNo; + pThisRowInfo->pCellInfo = new CellInfo[ nRotMax+1+2 ]; // vom Aufrufer zu loeschen ! + + for (nArrX=0; nArrX<=nRotMax+2; nArrX++) // Zell-Infos vorbelegen + { + if (nArrX>0) + nX = nArrX-1; + else + nX = MAXCOL+1; // ungueltig + + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX]; + pInfo->bEmptyCellText = TRUE; + pInfo->pCell = NULL; + if (bPaintMarks) + pInfo->bMarked = ( nX >= nBlockStartX && nX <= nBlockEndX + && nY >= nBlockStartY && nY <= nBlockEndY ); + else + pInfo->bMarked = FALSE; + pInfo->nWidth = 0; + + pInfo->nClipMark = SC_CLIPMARK_NONE; + pInfo->bMerged = FALSE; + pInfo->bHOverlapped = FALSE; + pInfo->bVOverlapped = FALSE; + pInfo->bAutoFilter = FALSE; + pInfo->bPushButton = FALSE; + pInfo->bPopupButton = false; + pInfo->bFilterActive = false; + pInfo->nRotateDir = SC_ROTDIR_NONE; + + pInfo->bPrinted = FALSE; // view-intern + pInfo->bHideGrid = FALSE; // view-intern + pInfo->bEditEngine = FALSE; // view-intern + + pInfo->pBackground = NULL; //! weglassen? + pInfo->pPatternAttr = NULL; + pInfo->pConditionSet= NULL; + + pInfo->pLinesAttr = NULL; + pInfo->mpTLBRLine = NULL; + pInfo->mpBLTRLine = NULL; + + pInfo->pShadowAttr = pDefShadow; + pInfo->pHShadowOrigin = NULL; + pInfo->pVShadowOrigin = NULL; + } + } + + for (nArrX=nX2+3; nArrX<=nRotMax+2; nArrX++) // restliche Breiten eintragen + { + nX = nArrX-1; + if ( ValidCol(nX) ) + { + if (!ColHidden(nX, nTab)) + { + USHORT nThisWidth = (USHORT) (GetColWidth( nX, nTab ) * nScaleX); + if (!nThisWidth) + nThisWidth = 1; + + pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth; + } + } + } + + for (nArrX=0; nArrX<=nX2+2; nArrX++) // links & rechts + 1 + { + nX = (nArrX>0) ? nArrX-1 : MAXCOL+1; // negativ -> ungueltig + + if ( ValidCol(nX) ) + { + // #i58049#, #i57939# Hidden columns must be skipped here, or their attributes + // will disturb the output + + // TODO: Optimize this loop. + if (!ColHidden(nX, nTab)) + { + USHORT nThisWidth = (USHORT) (GetColWidth( nX, nTab ) * nScaleX); + if (!nThisWidth) + nThisWidth = 1; + + pRowInfo[0].pCellInfo[nArrX].nWidth = nThisWidth; //! dies sollte reichen + + ScColumn* pThisCol = &pTab[nTab]->aCol[nX]; // Spalten-Daten + + nArrY = 1; + SCSIZE nUIndex; + bool bHiddenRow = true; + SCROW nHiddenEndRow = -1; + (void) pThisCol->Search( nY1, nUIndex ); + while ( nUIndex < pThisCol->nCount && + (nThisRow=pThisCol->pItems[nUIndex].nRow) <= nY2 ) + { + if (nThisRow > nHiddenEndRow) + bHiddenRow = RowHidden( nThisRow, nTab, nHiddenEndRow); + if ( !bHiddenRow ) + { + while ( pRowInfo[nArrY].nRowNo < nThisRow ) + ++nArrY; + DBG_ASSERT( pRowInfo[nArrY].nRowNo == nThisRow, "Zeile nicht gefunden in FillInfo" ); + + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX]; + pInfo->pCell = pThisCol->pItems[nUIndex].pCell; + if (pInfo->pCell->GetCellType() != CELLTYPE_NOTE) + { + pThisRowInfo->bEmptyText = FALSE; // Zeile nicht leer + pInfo->bEmptyCellText = FALSE; // Zelle nicht leer + } + ++nArrY; + } + ++nUIndex; + } + + if (nX+1 >= nX1) // Attribute/Blockmarken ab nX1-1 + { + ScAttrArray* pThisAttrArr = pThisCol->pAttrArray; // Attribute + + nArrY = 0; + const ScPatternAttr* pPattern; + SCROW nCurRow=nY1; // einzelne Zeile + if (nCurRow>0) + --nCurRow; // oben 1 mehr + else + nArrY = 1; + nThisRow=nCurRow; // Ende des Bereichs + SCSIZE nIndex; + (void) pThisAttrArr->Search( nCurRow, nIndex ); + + + do + { + nThisRow=pThisAttrArr->pData[nIndex].nRow; // Ende des Bereichs + pPattern=pThisAttrArr->pData[nIndex].pPattern; + + const SvxBrushItem* pBackground = (const SvxBrushItem*) + &pPattern->GetItem(ATTR_BACKGROUND); + const SvxBoxItem* pLinesAttr = (const SvxBoxItem*) + &pPattern->GetItem(ATTR_BORDER); + + const SvxLineItem* pTLBRLine = static_cast< const SvxLineItem* >( + &pPattern->GetItem( ATTR_BORDER_TLBR ) ); + const SvxLineItem* pBLTRLine = static_cast< const SvxLineItem* >( + &pPattern->GetItem( ATTR_BORDER_BLTR ) ); + + const SvxShadowItem* pShadowAttr = (const SvxShadowItem*) + &pPattern->GetItem(ATTR_SHADOW); + if (pShadowAttr != pDefShadow) + bAnyShadow = TRUE; + + const ScMergeAttr* pMergeAttr = (const ScMergeAttr*) + &pPattern->GetItem(ATTR_MERGE); + BOOL bMerged = ( pMergeAttr != pDefMerge && *pMergeAttr != *pDefMerge ); + USHORT nOverlap = ((const ScMergeFlagAttr*) &pPattern->GetItemSet(). + Get(ATTR_MERGE_FLAG))->GetValue(); + BOOL bHOverlapped = ((nOverlap & SC_MF_HOR) != 0); + BOOL bVOverlapped = ((nOverlap & SC_MF_VER) != 0); + BOOL bAutoFilter = ((nOverlap & SC_MF_AUTO) != 0); + BOOL bPushButton = ((nOverlap & SC_MF_BUTTON) != 0); + BOOL bScenario = ((nOverlap & SC_MF_SCENARIO) != 0); + bool bPopupButton = ((nOverlap & SC_MF_BUTTON_POPUP) != 0); + bool bFilterActive = ((nOverlap & SC_MF_HIDDEN_MEMBER) != 0); + if (bMerged||bHOverlapped||bVOverlapped) + bAnyMerged = TRUE; // intern + + BOOL bHidden, bHideFormula; + if (bTabProtect) + { + const ScProtectionAttr& rProtAttr = (const ScProtectionAttr&) + pPattern->GetItem(ATTR_PROTECTION); + bHidden = rProtAttr.GetHideCell(); + bHideFormula = rProtAttr.GetHideFormula(); + } + else + bHidden = bHideFormula = FALSE; + + ULONG nConditional = ((const SfxUInt32Item&)pPattern-> + GetItem(ATTR_CONDITIONAL)).GetValue(); + const ScConditionalFormat* pCondForm = NULL; + if ( nConditional && pCondFormList ) + pCondForm = pCondFormList->GetFormat( nConditional ); + + do + { + SCROW nLastHiddenRow = -1; + bool bRowHidden = RowHidden(nCurRow, nTab, nLastHiddenRow); + if ( nArrY==0 || !bRowHidden ) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + if (pBackground != pDefBackground) // Spalten-HG == Standard ? + pThisRowInfo->bEmptyBack = FALSE; + if (bAutoFilter) + pThisRowInfo->bAutoFilter = TRUE; + if (bPushButton) + pThisRowInfo->bPushButton = TRUE; + + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX]; + pInfo->pBackground = pBackground; + pInfo->pPatternAttr = pPattern; + pInfo->bMerged = bMerged; + pInfo->bHOverlapped = bHOverlapped; + pInfo->bVOverlapped = bVOverlapped; + pInfo->bAutoFilter = bAutoFilter; + pInfo->bPushButton = bPushButton; + pInfo->bPopupButton = bPopupButton; + pInfo->bFilterActive = bFilterActive; + pInfo->pLinesAttr = pLinesAttr; + pInfo->mpTLBRLine = pTLBRLine; + pInfo->mpBLTRLine = pBLTRLine; + pInfo->pShadowAttr = pShadowAttr; + // nWidth wird nicht mehr einzeln gesetzt + + BOOL bEmbed = FALSE; //bIsEmbedded && + nTab >= aEmbedRange.aStart.Tab() && + nTab <= aEmbedRange.aEnd.Tab() && + nX >= aEmbedRange.aStart.Col() && + nX <= aEmbedRange.aEnd.Col() && + nCurRow >= aEmbedRange.aStart.Row() && + nCurRow <= aEmbedRange.aEnd.Row(); + + if (bScenario) + { + pInfo->pBackground = ScGlobal::GetButtonBrushItem(); + pThisRowInfo->bEmptyBack = FALSE; + } + else if (bEmbed) + { + pInfo->pBackground = ScGlobal::GetEmbeddedBrushItem(); + pThisRowInfo->bEmptyBack = FALSE; + } + + if (bHidden || ( bFormulaMode && bHideFormula && pInfo->pCell + && pInfo->pCell->GetCellType() + == CELLTYPE_FORMULA )) + pInfo->bEmptyCellText = TRUE; + + if ( pCondForm ) + { + String aStyle = pCondForm->GetCellStyle( pInfo->pCell, + ScAddress( nX, nCurRow, nTab ) ); + if (aStyle.Len()) + { + SfxStyleSheetBase* pStyleSheet = + pStlPool->Find( aStyle, SFX_STYLE_FAMILY_PARA ); + if ( pStyleSheet ) + { + //! Style-Sets cachen !!! + pInfo->pConditionSet = &pStyleSheet->GetItemSet(); + bAnyCondition = TRUE; + } + // if style is not there, treat like no condition + } + } + + ++nArrY; + } + else if (bRowHidden && nLastHiddenRow >= 0) + { + nCurRow = nLastHiddenRow; + if (nCurRow > nThisRow) + nCurRow = nThisRow; + } + ++nCurRow; + } + while (nCurRow <= nThisRow && nCurRow <= nYExtra); + ++nIndex; + } + while ( nIndex < pThisAttrArr->nCount && nThisRow < nYExtra ); + + + if (pMarkData && pMarkData->IsMultiMarked()) + { + // Blockmarken + const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nX; + BOOL bThisMarked; + nArrY = 1; + nCurRow = nY1; // einzelne Zeile + nThisRow = nY1; // Ende des Bereichs + + if ( pThisMarkArr->Search( nY1, nIndex ) ) + { + do + { + nThisRow=pThisMarkArr->pData[nIndex].nRow; // Ende des Bereichs + bThisMarked=pThisMarkArr->pData[nIndex].bMarked; + + do + { + if ( !RowHidden( nCurRow,nTab ) ) + { + if ( bThisMarked ) + { + BOOL bSkip = bSkipMarks && + nX >= nBlockStartX && + nX <= nBlockEndX && + nCurRow >= nBlockStartY && + nCurRow <= nBlockEndY; + if (!bSkip) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX]; + pInfo->bMarked = TRUE; + } + } + ++nArrY; + } + ++nCurRow; + } + while (nCurRow <= nThisRow && nCurRow <= nY2); + ++nIndex; + } + while ( nIndex < pThisMarkArr->nCount && nThisRow < nY2 ); + } + } + } + else // vordere Spalten + { + for (nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX]; + + pInfo->nWidth = nThisWidth; //! oder nur 0 abfragen ?? + } + } + } + } + else + pRowInfo[0].pCellInfo[nArrX].nWidth = STD_COL_WIDTH; + // STD_COL_WIDTH ganz links und rechts wird fuer DrawExtraShadow gebraucht + } + + //------------------------------------------------------------------------- + // bedingte Formatierung auswerten + + if (bAnyCondition) + { + for (nArrY=0; nArrY<nArrCount; nArrY++) + { + for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr + { + CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX]; + const SfxItemSet* pCondSet = pInfo->pConditionSet; + if (pCondSet) + { + const SfxPoolItem* pItem; + + // Hintergrund + if ( pCondSet->GetItemState( ATTR_BACKGROUND, TRUE, &pItem ) == SFX_ITEM_SET ) + { + pInfo->pBackground = (const SvxBrushItem*) pItem; + pRowInfo[nArrY].bEmptyBack = FALSE; + } + + // Umrandung + if ( pCondSet->GetItemState( ATTR_BORDER, TRUE, &pItem ) == SFX_ITEM_SET ) + pInfo->pLinesAttr = (const SvxBoxItem*) pItem; + + if ( pCondSet->GetItemState( ATTR_BORDER_TLBR, TRUE, &pItem ) == SFX_ITEM_SET ) + pInfo->mpTLBRLine = static_cast< const SvxLineItem* >( pItem ); + if ( pCondSet->GetItemState( ATTR_BORDER_BLTR, TRUE, &pItem ) == SFX_ITEM_SET ) + pInfo->mpBLTRLine = static_cast< const SvxLineItem* >( pItem ); + + // Schatten + if ( pCondSet->GetItemState( ATTR_SHADOW, TRUE, &pItem ) == SFX_ITEM_SET ) + { + pInfo->pShadowAttr = (const SvxShadowItem*) pItem; + bAnyShadow = TRUE; + } + } + } + } + } + + // bedingte Formatierung Ende + //------------------------------------------------------------------------- + + // + // Daten von zusammengefassten Zellen anpassen + // + + if (bAnyMerged) + { + for (nArrY=0; nArrY<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + nSignedY = nArrY ? pThisRowInfo->nRowNo : ((SCsROW)nY1)-1; + + for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr + { + SCsCOL nSignedX = ((SCsCOL) nArrX) - 1; + CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX]; + + if (pInfo->bMerged || pInfo->bHOverlapped || pInfo->bVOverlapped) + { + SCsCOL nStartX; + SCsROW nStartY; + SCsCOL nEndX; + SCsROW nEndY; + lcl_GetMergeRange( nSignedX,nSignedY, nArrY, this,pRowInfo, nX1,nY1,nX2,nY2,nTab, + nStartX,nStartY, nEndX,nEndY ); + const ScPatternAttr* pStartPattern = GetPattern( nStartX,nStartY,nTab ); + const SfxItemSet* pStartCond = GetCondResult( nStartX,nStartY,nTab ); + const SfxPoolItem* pItem; + + // Hintergrund kopieren (oder in output.cxx) + + if ( !pStartCond || pStartCond-> + GetItemState(ATTR_BACKGROUND,TRUE,&pItem) != SFX_ITEM_SET ) + pItem = &pStartPattern->GetItem(ATTR_BACKGROUND); + pInfo->pBackground = (const SvxBrushItem*) pItem; + pRowInfo[nArrY].bEmptyBack = FALSE; + + // Schatten + + if ( !pStartCond || pStartCond-> + GetItemState(ATTR_SHADOW,TRUE,&pItem) != SFX_ITEM_SET ) + pItem = &pStartPattern->GetItem(ATTR_SHADOW); + pInfo->pShadowAttr = (const SvxShadowItem*) pItem; + if (pInfo->pShadowAttr != pDefShadow) + bAnyShadow = TRUE; + + // Blockmarken - wieder mit Original-Merge-Werten + + BOOL bCellMarked = FALSE; + if (bPaintMarks) + bCellMarked = ( nStartX >= (SCsCOL) nBlockStartX + && nStartX <= (SCsCOL) nBlockEndX + && nStartY >= (SCsROW) nBlockStartY + && nStartY <= (SCsROW) nBlockEndY ); + if (pMarkData && pMarkData->IsMultiMarked() && !bCellMarked) + { + const ScMarkArray* pThisMarkArr = pMarkData->GetArray()+nStartX; + SCSIZE nIndex; + if ( pThisMarkArr->Search( nStartY, nIndex ) ) + bCellMarked=pThisMarkArr->pData[nIndex].bMarked; + } + + pInfo->bMarked = bCellMarked; + } + } + } + } + + if (bAnyShadow) // Schatten verteilen + { + for (nArrY=0; nArrY<nArrCount; nArrY++) + { + BOOL bTop = ( nArrY == 0 ); + BOOL bBottom = ( nArrY+1 == nArrCount ); + + for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr + { + BOOL bLeft = ( nArrX == nX1 ); + BOOL bRight = ( nArrX == nX2+2 ); + + CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nArrX]; + const SvxShadowItem* pThisAttr = pInfo->pShadowAttr; + SvxShadowLocation eLoc = pThisAttr ? pThisAttr->GetLocation() : SVX_SHADOW_NONE; + if (eLoc != SVX_SHADOW_NONE) + { + // oder Test auf != eLoc + + SCsCOL nDxPos = 1; + SCsCOL nDxNeg = -1; + + while ( nArrX+nDxPos < nX2+2 && pRowInfo[0].pCellInfo[nArrX+nDxPos].nWidth == 0 ) + ++nDxPos; + while ( nArrX+nDxNeg > nX1 && pRowInfo[0].pCellInfo[nArrX+nDxNeg].nWidth == 0 ) + --nDxNeg; + + BOOL bLeftDiff = !bLeft && + CELLINFO(nDxNeg,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE; + BOOL bRightDiff = !bRight && + CELLINFO(nDxPos,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE; + BOOL bTopDiff = !bTop && + CELLINFO(0,-1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE; + BOOL bBottomDiff = !bBottom && + CELLINFO(0,1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE; + + if ( bLayoutRTL ) + { + switch (eLoc) + { + case SVX_SHADOW_BOTTOMRIGHT: eLoc = SVX_SHADOW_BOTTOMLEFT; break; + case SVX_SHADOW_BOTTOMLEFT: eLoc = SVX_SHADOW_BOTTOMRIGHT; break; + case SVX_SHADOW_TOPRIGHT: eLoc = SVX_SHADOW_TOPLEFT; break; + case SVX_SHADOW_TOPLEFT: eLoc = SVX_SHADOW_TOPRIGHT; break; + default: + { + // added to avoid warnings + } + } + } + + switch (eLoc) + { + case SVX_SHADOW_BOTTOMRIGHT: + if (bBottomDiff) + { + CELLINFO(0,1).pHShadowOrigin = pThisAttr; + CELLINFO(0,1).eHShadowPart = + bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ; + } + if (bRightDiff) + { + CELLINFO(1,0).pVShadowOrigin = pThisAttr; + CELLINFO(1,0).eVShadowPart = + bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT; + } + if (bBottomDiff && bRightDiff) + { + CELLINFO(1,1).pHShadowOrigin = pThisAttr; + CELLINFO(1,1).eHShadowPart = SC_SHADOW_CORNER; + } + break; + + case SVX_SHADOW_BOTTOMLEFT: + if (bBottomDiff) + { + CELLINFO(0,1).pHShadowOrigin = pThisAttr; + CELLINFO(0,1).eHShadowPart = + bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ; + } + if (bLeftDiff) + { + CELLINFO(-1,0).pVShadowOrigin = pThisAttr; + CELLINFO(-1,0).eVShadowPart = + bTopDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT; + } + if (bBottomDiff && bLeftDiff) + { + CELLINFO(-1,1).pHShadowOrigin = pThisAttr; + CELLINFO(-1,1).eHShadowPart = SC_SHADOW_CORNER; + } + break; + + case SVX_SHADOW_TOPRIGHT: + if (bTopDiff) + { + CELLINFO(0,-1).pHShadowOrigin = pThisAttr; + CELLINFO(0,-1).eHShadowPart = + bLeftDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ; + } + if (bRightDiff) + { + CELLINFO(1,0).pVShadowOrigin = pThisAttr; + CELLINFO(1,0).eVShadowPart = + bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT; + } + if (bTopDiff && bRightDiff) + { + CELLINFO(1,-1).pHShadowOrigin = pThisAttr; + CELLINFO(1,-1).eHShadowPart = SC_SHADOW_CORNER; + } + break; + + case SVX_SHADOW_TOPLEFT: + if (bTopDiff) + { + CELLINFO(0,-1).pHShadowOrigin = pThisAttr; + CELLINFO(0,-1).eHShadowPart = + bRightDiff ? SC_SHADOW_HSTART : SC_SHADOW_HORIZ; + } + if (bLeftDiff) + { + CELLINFO(-1,0).pVShadowOrigin = pThisAttr; + CELLINFO(-1,0).eVShadowPart = + bBottomDiff ? SC_SHADOW_VSTART : SC_SHADOW_VERT; + } + if (bTopDiff && bLeftDiff) + { + CELLINFO(-1,-1).pHShadowOrigin = pThisAttr; + CELLINFO(-1,-1).eHShadowPart = SC_SHADOW_CORNER; + } + break; + + default: + DBG_ERROR("falscher Shadow-Enum"); + } + } + } + } + } + + rTabInfo.mnArrCount = sal::static_int_cast<USHORT>(nArrCount); + rTabInfo.mbPageMode = bPageMode; + + // ======================================================================== + // *** create the frame border array *** + + // RowInfo structs are filled in the range [ 0 , nArrCount-1 ] + // each RowInfo contains CellInfo structs in the range [ nX1-1 , nX2+1 ] + + size_t nColCount = nX2 - nX1 + 3; + size_t nRowCount = nArrCount; + + svx::frame::Array& rArray = rTabInfo.maArray; + rArray.Initialize( nColCount, nRowCount ); + rArray.SetUseDiagDoubleClipping( false ); + + for( size_t nRow = 0; nRow < nRowCount; ++nRow ) + { + USHORT nCellInfoY = static_cast< USHORT >( nRow ); + RowInfo& rThisRowInfo = pRowInfo[ nCellInfoY ]; + + for( size_t nCol = 0; nCol < nColCount; ++nCol ) + { + USHORT nCellInfoX = static_cast< USHORT >( nCol + nX1 ); + const CellInfo& rInfo = rThisRowInfo.pCellInfo[ nCellInfoX ]; + + const SvxBoxItem* pBox = rInfo.pLinesAttr; + const SvxLineItem* pTLBR = rInfo.mpTLBRLine; + const SvxLineItem* pBLTR = rInfo.mpBLTRLine; + + size_t nFirstCol = nCol; + size_t nFirstRow = nRow; + + // *** merged cells *** ------------------------------------------- + + if( !rArray.IsMerged( nCol, nRow ) && (rInfo.bMerged || rInfo.bHOverlapped || rInfo.bVOverlapped) ) + { + // *** insert merged range in svx::frame::Array *** + + /* #i69369# top-left cell of a merged range may be located in + a hidden column or row. Use lcl_GetMergeRange() to find the + complete merged range, then calculate dimensions and + document position of the visible range. */ + + // note: document columns are always one less than CellInfoX coords + // note: document rows must be looked up in RowInfo structs + + // current column and row in document coordinates + SCCOL nCurrDocCol = static_cast< SCCOL >( nCellInfoX - 1 ); + SCROW nCurrDocRow = static_cast< SCROW >( (nCellInfoY > 0) ? rThisRowInfo.nRowNo : (nY1 - 1) ); + + // find entire merged range in document, returns signed document coordinates + SCsCOL nFirstRealDocColS, nLastRealDocColS; + SCsROW nFirstRealDocRowS, nLastRealDocRowS; + lcl_GetMergeRange( static_cast< SCsCOL >( nCurrDocCol ), static_cast< SCsROW >( nCurrDocRow ), + nCellInfoY, this, pRowInfo, nX1,nY1,nX2,nY2,nTab, + nFirstRealDocColS, nFirstRealDocRowS, nLastRealDocColS, nLastRealDocRowS ); + + // *complete* merged range in document coordinates + SCCOL nFirstRealDocCol = static_cast< SCCOL >( nFirstRealDocColS ); + SCROW nFirstRealDocRow = static_cast< SCROW >( nFirstRealDocRowS ); + SCCOL nLastRealDocCol = static_cast< SCCOL >( nLastRealDocColS ); + SCROW nLastRealDocRow = static_cast< SCROW >( nLastRealDocRowS ); + + // first visible column (nX1-1 is first processed document column) + SCCOL nFirstDocCol = (nX1 > 0) ? ::std::max< SCCOL >( nFirstRealDocCol, nX1 - 1 ) : nFirstRealDocCol; + USHORT nFirstCellInfoX = static_cast< USHORT >( nFirstDocCol + 1 ); + nFirstCol = static_cast< size_t >( nFirstCellInfoX - nX1 ); + + // last visible column (nX2+1 is last processed document column) + SCCOL nLastDocCol = (nX2 < MAXCOL) ? ::std::min< SCCOL >( nLastRealDocCol, nX2 + 1 ) : nLastRealDocCol; + USHORT nLastCellInfoX = static_cast< USHORT >( nLastDocCol + 1 ); + size_t nLastCol = static_cast< size_t >( nLastCellInfoX - nX1 ); + + // first visible row + USHORT nFirstCellInfoY = nCellInfoY; + while( ((nFirstCellInfoY > 1) && (pRowInfo[ nFirstCellInfoY - 1 ].nRowNo >= nFirstRealDocRow)) || + ((nFirstCellInfoY == 1) && (static_cast< SCROW >( nY1 - 1 ) >= nFirstRealDocRow)) ) + --nFirstCellInfoY; + SCROW nFirstDocRow = (nFirstCellInfoY > 0) ? pRowInfo[ nFirstCellInfoY ].nRowNo : static_cast< SCROW >( nY1 - 1 ); + nFirstRow = static_cast< size_t >( nFirstCellInfoY ); + + // last visible row + USHORT nLastCellInfoY = nCellInfoY; + while( (sal::static_int_cast<SCSIZE>(nLastCellInfoY + 1) < nArrCount) && + (pRowInfo[ nLastCellInfoY + 1 ].nRowNo <= nLastRealDocRow) ) + ++nLastCellInfoY; + SCROW nLastDocRow = (nLastCellInfoY > 0) ? pRowInfo[ nLastCellInfoY ].nRowNo : static_cast< SCROW >( nY1 - 1 ); + size_t nLastRow = static_cast< size_t >( nLastCellInfoY ); + + // insert merged range + rArray.SetMergedRange( nFirstCol, nFirstRow, nLastCol, nLastRow ); + + // *** find additional size not included in svx::frame::Array *** + + // additional space before first column + if( nFirstCol == 0 ) + { + long nSize = 0; + for( SCCOL nDocCol = nFirstRealDocCol; nDocCol < nFirstDocCol; ++nDocCol ) + nSize += std::max( static_cast< long >( GetColWidth( nDocCol, nTab ) * nScaleX ), 1L ); + rArray.SetAddMergedLeftSize( nCol, nRow, nSize ); + } + // additional space after last column + if( nLastCol + 1 == nColCount ) + { + long nSize = 0; + for( SCCOL nDocCol = nLastDocCol + 1; nDocCol <= nLastRealDocCol; ++nDocCol ) + nSize += std::max( static_cast< long >( GetColWidth( nDocCol, nTab ) * nScaleX ), 1L ); + rArray.SetAddMergedRightSize( nCol, nRow, nSize ); + } + // additional space above first row + if( nFirstRow == 0 ) + { + long nSize = 0; + for( SCROW nDocRow = nFirstRealDocRow; nDocRow < nFirstDocRow; ++nDocRow ) + nSize += std::max( static_cast< long >( GetRowHeight( nDocRow, nTab ) * nScaleY ), 1L ); + rArray.SetAddMergedTopSize( nCol, nRow, nSize ); + } + // additional space beyond last row + if( nLastRow + 1 == nRowCount ) + { + long nSize = 0; + for( SCROW nDocRow = nLastDocRow + 1; nDocRow <= nLastRealDocRow; ++nDocRow ) + nSize += std::max( static_cast< long >( GetRowHeight( nDocRow, nTab ) * nScaleY ), 1L ); + rArray.SetAddMergedBottomSize( nCol, nRow, nSize ); + } + + // *** use line attributes from real origin cell *** + + if( (nFirstRealDocCol != nCurrDocCol) || (nFirstRealDocRow != nCurrDocRow) ) + { + if( const ScPatternAttr* pPattern = GetPattern( nFirstRealDocCol, nFirstRealDocRow, nTab ) ) + { + const SfxItemSet* pCond = GetCondResult( nFirstRealDocCol, nFirstRealDocRow, nTab ); + pBox = static_cast< const SvxBoxItem* >( &pPattern->GetItem( ATTR_BORDER, pCond ) ); + pTLBR = static_cast< const SvxLineItem* >( &pPattern->GetItem( ATTR_BORDER_TLBR, pCond ) ); + pBLTR = static_cast< const SvxLineItem* >( &pPattern->GetItem( ATTR_BORDER_BLTR, pCond ) ); + } + else + { + pBox = 0; + pTLBR = pBLTR = 0; + } + } + } + + // *** borders *** ------------------------------------------------ + + if( pBox ) + { + rArray.SetCellStyleLeft( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetLeft(), nScaleX ) ); + rArray.SetCellStyleRight( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetRight(), nScaleX ) ); + rArray.SetCellStyleTop( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetTop(), nScaleY ) ); + rArray.SetCellStyleBottom( nFirstCol, nFirstRow, svx::frame::Style( pBox->GetBottom(), nScaleY ) ); + } + + if( pTLBR ) + rArray.SetCellStyleTLBR( nFirstCol, nFirstRow, svx::frame::Style( pTLBR->GetLine(), nScaleY ) ); + if( rInfo.mpBLTRLine ) + rArray.SetCellStyleBLTR( nFirstCol, nFirstRow, svx::frame::Style( pBLTR->GetLine(), nScaleY ) ); + } + } + + /* Mirror the entire frame array. + 1st param = Mirror the vertical double line styles as well. + 2nd param = Do not swap diagonal lines. + */ + if( bLayoutRTL ) + rArray.MirrorSelfX( true, false ); +} + +// ============================================================================ + +ScTableInfo::ScTableInfo() : + mpRowInfo( new RowInfo[ ROWINFO_MAX ] ), + mbPageMode( false ) +{ + for( USHORT nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx ) + mpRowInfo[ nIdx ].pCellInfo = 0; +} + +ScTableInfo::~ScTableInfo() +{ + for( USHORT nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx ) + delete [] mpRowInfo[ nIdx ].pCellInfo; + delete [] mpRowInfo; +} + +// ============================================================================ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |