| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 sal_uInt16 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; |
| sal_Bool bHOver = pInfo->bHOverlapped; |
| sal_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 |
| { |
| sal_uInt16 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 |
| { |
| sal_uInt16 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, |
| sal_Bool bPageMode, sal_Bool bFormulaMode, const ScMarkData* pMarkData ) |
| { |
| DBG_ASSERT( pTab[nTab], "Tabelle existiert nicht" ); |
| |
| sal_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; |
| sal_Bool bAnyMerged = sal_False; |
| sal_Bool bAnyShadow = sal_False; |
| sal_Bool bAnyCondition = sal_False; |
| |
| sal_Bool bTabProtect = IsTabProtected(nTab); |
| |
| // fuer Blockmarken von zusammengefassten Zellen mit |
| // versteckter erster Zeile / Spalte |
| sal_Bool bPaintMarks = sal_False; |
| sal_Bool bSkipMarks = sal_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 = sal_True; |
| else |
| bPaintMarks = sal_True; |
| } |
| } |
| |
| // zuerst nur die Eintraege fuer die ganze Spalte |
| |
| nArrY=0; |
| SCROW nYExtra = nY2+1; |
| sal_uInt16 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 |
| |
| sal_uInt16 nHeight = (sal_uInt16) ( nDocHeight * nScaleY ); |
| if (!nHeight) |
| nHeight = 1; |
| |
| pThisRowInfo->nRowNo = nY; //! Fall < 0 ? |
| pThisRowInfo->nHeight = nHeight; |
| pThisRowInfo->bEmptyBack = sal_True; |
| pThisRowInfo->bEmptyText = sal_True; |
| pThisRowInfo->bChanged = sal_True; |
| pThisRowInfo->bAutoFilter = sal_False; |
| pThisRowInfo->bPushButton = sal_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? |
| sal_Bool bAnyItem = sal_False; |
| sal_uInt32 nRotCount = pPool->GetItemCount2( ATTR_ROTATE_VALUE ); |
| for (sal_uInt32 nItem=0; nItem<nRotCount; nItem++) |
| if (pPool->GetItem2( ATTR_ROTATE_VALUE, nItem )) |
| { |
| bAnyItem = sal_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 = sal_True; |
| pInfo->pCell = NULL; |
| if (bPaintMarks) |
| pInfo->bMarked = ( nX >= nBlockStartX && nX <= nBlockEndX |
| && nY >= nBlockStartY && nY <= nBlockEndY ); |
| else |
| pInfo->bMarked = sal_False; |
| pInfo->nWidth = 0; |
| |
| pInfo->nClipMark = SC_CLIPMARK_NONE; |
| pInfo->bMerged = sal_False; |
| pInfo->bHOverlapped = sal_False; |
| pInfo->bVOverlapped = sal_False; |
| pInfo->bAutoFilter = sal_False; |
| pInfo->bPushButton = sal_False; |
| pInfo->bPopupButton = false; |
| pInfo->bFilterActive = false; |
| pInfo->nRotateDir = SC_ROTDIR_NONE; |
| |
| pInfo->bPrinted = sal_False; // view-intern |
| pInfo->bHideGrid = sal_False; // view-intern |
| pInfo->bEditEngine = sal_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)) |
| { |
| sal_uInt16 nThisWidth = (sal_uInt16) (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)) |
| { |
| sal_uInt16 nThisWidth = (sal_uInt16) (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 = sal_False; // Zeile nicht leer |
| pInfo->bEmptyCellText = sal_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 = sal_True; |
| |
| const ScMergeAttr* pMergeAttr = (const ScMergeAttr*) |
| &pPattern->GetItem(ATTR_MERGE); |
| sal_Bool bMerged = ( pMergeAttr != pDefMerge && *pMergeAttr != *pDefMerge ); |
| sal_uInt16 nOverlap = ((const ScMergeFlagAttr*) &pPattern->GetItemSet(). |
| Get(ATTR_MERGE_FLAG))->GetValue(); |
| sal_Bool bHOverlapped = ((nOverlap & SC_MF_HOR) != 0); |
| sal_Bool bVOverlapped = ((nOverlap & SC_MF_VER) != 0); |
| sal_Bool bAutoFilter = ((nOverlap & SC_MF_AUTO) != 0); |
| sal_Bool bPushButton = ((nOverlap & SC_MF_BUTTON) != 0); |
| sal_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 = sal_True; // intern |
| |
| sal_Bool bHidden, bHideFormula; |
| if (bTabProtect) |
| { |
| const ScProtectionAttr& rProtAttr = (const ScProtectionAttr&) |
| pPattern->GetItem(ATTR_PROTECTION); |
| bHidden = rProtAttr.GetHideCell(); |
| bHideFormula = rProtAttr.GetHideFormula(); |
| } |
| else |
| bHidden = bHideFormula = sal_False; |
| |
| sal_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 = sal_False; |
| if (bAutoFilter) |
| pThisRowInfo->bAutoFilter = sal_True; |
| if (bPushButton) |
| pThisRowInfo->bPushButton = sal_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 |
| |
| sal_Bool bEmbed = sal_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 = sal_False; |
| } |
| else if (bEmbed) |
| { |
| pInfo->pBackground = ScGlobal::GetEmbeddedBrushItem(); |
| pThisRowInfo->bEmptyBack = sal_False; |
| } |
| |
| if (bHidden || ( bFormulaMode && bHideFormula && pInfo->pCell |
| && pInfo->pCell->GetCellType() |
| == CELLTYPE_FORMULA )) |
| pInfo->bEmptyCellText = sal_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 = sal_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; |
| sal_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 ) |
| { |
| sal_Bool bSkip = bSkipMarks && |
| nX >= nBlockStartX && |
| nX <= nBlockEndX && |
| nCurRow >= nBlockStartY && |
| nCurRow <= nBlockEndY; |
| if (!bSkip) |
| { |
| RowInfo* pThisRowInfo = &pRowInfo[nArrY]; |
| CellInfo* pInfo = &pThisRowInfo->pCellInfo[nArrX]; |
| pInfo->bMarked = sal_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, sal_True, &pItem ) == SFX_ITEM_SET ) |
| { |
| pInfo->pBackground = (const SvxBrushItem*) pItem; |
| pRowInfo[nArrY].bEmptyBack = sal_False; |
| } |
| |
| // Umrandung |
| if ( pCondSet->GetItemState( ATTR_BORDER, sal_True, &pItem ) == SFX_ITEM_SET ) |
| pInfo->pLinesAttr = (const SvxBoxItem*) pItem; |
| |
| if ( pCondSet->GetItemState( ATTR_BORDER_TLBR, sal_True, &pItem ) == SFX_ITEM_SET ) |
| pInfo->mpTLBRLine = static_cast< const SvxLineItem* >( pItem ); |
| if ( pCondSet->GetItemState( ATTR_BORDER_BLTR, sal_True, &pItem ) == SFX_ITEM_SET ) |
| pInfo->mpBLTRLine = static_cast< const SvxLineItem* >( pItem ); |
| |
| // Schatten |
| if ( pCondSet->GetItemState( ATTR_SHADOW, sal_True, &pItem ) == SFX_ITEM_SET ) |
| { |
| pInfo->pShadowAttr = (const SvxShadowItem*) pItem; |
| bAnyShadow = sal_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,sal_True,&pItem) != SFX_ITEM_SET ) |
| pItem = &pStartPattern->GetItem(ATTR_BACKGROUND); |
| pInfo->pBackground = (const SvxBrushItem*) pItem; |
| pRowInfo[nArrY].bEmptyBack = sal_False; |
| |
| // Schatten |
| |
| if ( !pStartCond || pStartCond-> |
| GetItemState(ATTR_SHADOW,sal_True,&pItem) != SFX_ITEM_SET ) |
| pItem = &pStartPattern->GetItem(ATTR_SHADOW); |
| pInfo->pShadowAttr = (const SvxShadowItem*) pItem; |
| if (pInfo->pShadowAttr != pDefShadow) |
| bAnyShadow = sal_True; |
| |
| // Blockmarken - wieder mit Original-Merge-Werten |
| |
| sal_Bool bCellMarked = sal_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++) |
| { |
| sal_Bool bTop = ( nArrY == 0 ); |
| sal_Bool bBottom = ( nArrY+1 == nArrCount ); |
| |
| for (nArrX=nX1; nArrX<=nX2+2; nArrX++) // links und rechts einer mehr |
| { |
| sal_Bool bLeft = ( nArrX == nX1 ); |
| sal_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; |
| |
| sal_Bool bLeftDiff = !bLeft && |
| CELLINFO(nDxNeg,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE; |
| sal_Bool bRightDiff = !bRight && |
| CELLINFO(nDxPos,0).pShadowAttr->GetLocation() == SVX_SHADOW_NONE; |
| sal_Bool bTopDiff = !bTop && |
| CELLINFO(0,-1).pShadowAttr->GetLocation() == SVX_SHADOW_NONE; |
| sal_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<sal_uInt16>(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 ) |
| { |
| sal_uInt16 nCellInfoY = static_cast< sal_uInt16 >( nRow ); |
| RowInfo& rThisRowInfo = pRowInfo[ nCellInfoY ]; |
| |
| for( size_t nCol = 0; nCol < nColCount; ++nCol ) |
| { |
| sal_uInt16 nCellInfoX = static_cast< sal_uInt16 >( 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; |
| sal_uInt16 nFirstCellInfoX = static_cast< sal_uInt16 >( 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; |
| sal_uInt16 nLastCellInfoX = static_cast< sal_uInt16 >( nLastDocCol + 1 ); |
| size_t nLastCol = static_cast< size_t >( nLastCellInfoX - nX1 ); |
| |
| // first visible row |
| sal_uInt16 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 |
| sal_uInt16 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( sal_uInt16 nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx ) |
| mpRowInfo[ nIdx ].pCellInfo = 0; |
| } |
| |
| ScTableInfo::~ScTableInfo() |
| { |
| for( sal_uInt16 nIdx = 0; nIdx < ROWINFO_MAX; ++nIdx ) |
| delete [] mpRowInfo[ nIdx ].pCellInfo; |
| delete [] mpRowInfo; |
| } |
| |
| // ============================================================================ |
| |