| /************************************************************** |
| * |
| * 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/eeitem.hxx> |
| |
| #include <svx/algitem.hxx> |
| #include <editeng/editobj.hxx> |
| #include <editeng/editstat.hxx> |
| #include <editeng/emphitem.hxx> |
| #include <editeng/fhgtitem.hxx> |
| #include <editeng/forbiddencharacterstable.hxx> |
| #include <svx/rotmodit.hxx> |
| #include <editeng/scripttypeitem.hxx> |
| #include <editeng/unolingu.hxx> |
| #include <svl/zforlist.hxx> |
| #include <svl/broadcast.hxx> |
| #include <svl/listeneriter.hxx> |
| #include <vcl/outdev.hxx> |
| |
| #include "column.hxx" |
| #include "cell.hxx" |
| #include "document.hxx" |
| #include "docpool.hxx" |
| #include "attarray.hxx" |
| #include "patattr.hxx" |
| #include "cellform.hxx" |
| #include "collect.hxx" |
| #include "stlsheet.hxx" |
| #include "rechead.hxx" |
| #include "brdcst.hxx" |
| #include "editutil.hxx" |
| #include "subtotal.hxx" |
| #include "markdata.hxx" |
| #include "compiler.hxx" // ScTokenArray GetCodeLen |
| #include "dbcolect.hxx" |
| #include "fillinfo.hxx" |
| #include "segmenttree.hxx" |
| |
| #include <math.h> |
| |
| // ----------------------------------------------------------------------- |
| |
| // factor from font size to optimal cell height (text width) |
| #define SC_ROT_BREAK_FACTOR 6 |
| |
| // ----------------------------------------------------------------------- |
| |
| inline sal_Bool IsAmbiguousScript( sal_uInt8 nScript ) |
| { |
| //! move to a header file |
| return ( nScript != SCRIPTTYPE_LATIN && |
| nScript != SCRIPTTYPE_ASIAN && |
| nScript != SCRIPTTYPE_COMPLEX ); |
| } |
| |
| // ----------------------------------------------------------------------------------------- |
| |
| // |
| // Datei-Operationen |
| // |
| |
| // ----------------------------------------------------------------------------------------- |
| |
| //UNUSED2008-05 SCROW ScColumn::NoteCount( SCROW nMaxRow ) const |
| //UNUSED2008-05 { |
| //UNUSED2008-05 SCROW nNoteCount = 0; |
| //UNUSED2008-05 SCSIZE i; |
| //UNUSED2008-05 |
| //UNUSED2008-05 for (i=0; i<nCount; i++) |
| //UNUSED2008-05 if ( pItems[i].pCell->GetNotePtr() && pItems[i].nRow<=nMaxRow ) |
| //UNUSED2008-05 ++nNoteCount; |
| //UNUSED2008-05 |
| //UNUSED2008-05 return nNoteCount; |
| //UNUSED2008-05 } |
| |
| // ----------------------------------------------------------------------------------------- |
| |
| //UNUSED2008-05 void ScColumn::CorrectSymbolCells( CharSet eStreamCharSet ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 // #99139# find and correct string cells that are formatted with a symbol font, |
| //UNUSED2008-05 // but are not in the LoadedSymbolStringCellsList |
| //UNUSED2008-05 // (because CELLTYPE_SYMBOLS wasn't written in the file) |
| //UNUSED2008-05 |
| //UNUSED2008-05 ScFontToSubsFontConverter_AutoPtr xFontConverter; |
| //UNUSED2008-05 const sal_uLong nFontConverterFlags = FONTTOSUBSFONT_EXPORT | FONTTOSUBSFONT_ONLYOLDSOSYMBOLFONTS; |
| //UNUSED2008-05 |
| //UNUSED2008-05 sal_Bool bListInitialized = sal_False; |
| //UNUSED2008-05 ScSymbolStringCellEntry* pCurrentEntry = NULL; |
| //UNUSED2008-05 |
| //UNUSED2008-05 ScAttrIterator aAttrIter( pAttrArray, 0, MAXROW ); |
| //UNUSED2008-05 SCROW nStt, nEnd; |
| //UNUSED2008-05 const ScPatternAttr* pAttr = aAttrIter.Next( nStt, nEnd ); |
| //UNUSED2008-05 while ( pAttr ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 if ( (xFontConverter = pAttr->GetSubsFontConverter( nFontConverterFlags )) || |
| //UNUSED2008-05 pAttr->IsSymbolFont() ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 ScColumnIterator aCellIter( this, nStt, nEnd ); |
| //UNUSED2008-05 SCROW nRow; |
| //UNUSED2008-05 ScBaseCell* pCell; |
| //UNUSED2008-05 while ( aCellIter.Next( nRow, pCell ) ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 if ( pCell->GetCellType() == CELLTYPE_STRING ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 List& rList = pDocument->GetLoadedSymbolStringCellsList(); |
| //UNUSED2008-05 if (!bListInitialized) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 pCurrentEntry = (ScSymbolStringCellEntry*)rList.First(); |
| //UNUSED2008-05 bListInitialized = sal_True; |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 while ( pCurrentEntry && pCurrentEntry->nRow < nRow ) |
| //UNUSED2008-05 pCurrentEntry = (ScSymbolStringCellEntry*)rList.Next(); |
| //UNUSED2008-05 |
| //UNUSED2008-05 if ( pCurrentEntry && pCurrentEntry->nRow == nRow ) |
| //UNUSED2008-05 { |
| //UNUSED2008-05 // found |
| //UNUSED2008-05 } |
| //UNUSED2008-05 else |
| //UNUSED2008-05 { |
| //UNUSED2008-05 // not in list -> convert and put into list |
| //UNUSED2008-05 |
| //UNUSED2008-05 ScStringCell* pStrCell = (ScStringCell*)pCell; |
| //UNUSED2008-05 String aOldStr; |
| //UNUSED2008-05 pStrCell->GetString( aOldStr ); |
| //UNUSED2008-05 |
| //UNUSED2008-05 // convert back to stream character set (get original data) |
| //UNUSED2008-05 ByteString aByteStr( aOldStr, eStreamCharSet ); |
| //UNUSED2008-05 |
| //UNUSED2008-05 // convert using symbol encoding, as for CELLTYPE_SYMBOLS cells |
| //UNUSED2008-05 String aNewStr( aByteStr, RTL_TEXTENCODING_SYMBOL ); |
| //UNUSED2008-05 pStrCell->SetString( aNewStr ); |
| //UNUSED2008-05 |
| //UNUSED2008-05 ScSymbolStringCellEntry * pEntry = new ScSymbolStringCellEntry; |
| //UNUSED2008-05 pEntry->pCell = pStrCell; |
| //UNUSED2008-05 pEntry->nRow = nRow; |
| //UNUSED2008-05 |
| //UNUSED2008-05 if ( pCurrentEntry ) |
| //UNUSED2008-05 rList.Insert( pEntry ); // before current entry - pCurrentEntry stays valid |
| //UNUSED2008-05 else |
| //UNUSED2008-05 rList.Insert( pEntry, LIST_APPEND ); // append if already behind last entry |
| //UNUSED2008-05 } |
| //UNUSED2008-05 } |
| //UNUSED2008-05 } |
| //UNUSED2008-05 } |
| //UNUSED2008-05 |
| //UNUSED2008-05 pAttr = aAttrIter.Next( nStt, nEnd ); |
| //UNUSED2008-05 } |
| //UNUSED2008-05 } |
| |
| // ----------------------------------------------------------------------------------------- |
| |
| // GetNeededSize: optimale Hoehe / Breite in Pixeln |
| |
| long ScColumn::GetNeededSize( SCROW nRow, OutputDevice* pDev, |
| double nPPTX, double nPPTY, |
| const Fraction& rZoomX, const Fraction& rZoomY, |
| sal_Bool bWidth, const ScNeededSizeOptions& rOptions ) |
| { |
| long nValue=0; |
| SCSIZE nIndex; |
| double nPPT = bWidth ? nPPTX : nPPTY; |
| if (Search(nRow,nIndex)) |
| { |
| ScBaseCell* pCell = pItems[nIndex].pCell; |
| const ScPatternAttr* pPattern = rOptions.pPattern; |
| if (!pPattern) |
| pPattern = pAttrArray->GetPattern( nRow ); |
| |
| // zusammengefasst? |
| // Merge nicht in bedingter Formatierung |
| |
| const ScMergeAttr* pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE); |
| const ScMergeFlagAttr* pFlag = (const ScMergeFlagAttr*)&pPattern->GetItem(ATTR_MERGE_FLAG); |
| |
| if ( bWidth ) |
| { |
| if ( pFlag->IsHorOverlapped() ) |
| return 0; |
| if ( rOptions.bSkipMerged && pMerge->GetColMerge() > 1 ) |
| return 0; |
| } |
| else |
| { |
| if ( pFlag->IsVerOverlapped() ) |
| return 0; |
| if ( rOptions.bSkipMerged && pMerge->GetRowMerge() > 1 ) |
| return 0; |
| } |
| |
| // bedingte Formatierung |
| const SfxItemSet* pCondSet = NULL; |
| if ( ((const SfxUInt32Item&)pPattern->GetItem(ATTR_CONDITIONAL)).GetValue() ) |
| pCondSet = pDocument->GetCondResult( nCol, nRow, nTab ); |
| |
| // Zeilenumbruch? |
| |
| const SfxPoolItem* pCondItem; |
| SvxCellHorJustify eHorJust; |
| if (pCondSet && |
| pCondSet->GetItemState(ATTR_HOR_JUSTIFY, sal_True, &pCondItem) == SFX_ITEM_SET) |
| eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem*)pCondItem)->GetValue(); |
| else |
| eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&) |
| pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue(); |
| bool bBreak; |
| if ( eHorJust == SVX_HOR_JUSTIFY_BLOCK ) |
| bBreak = true; |
| else if ( pCondSet && |
| pCondSet->GetItemState(ATTR_LINEBREAK, sal_True, &pCondItem) == SFX_ITEM_SET) |
| bBreak = ((const SfxBoolItem*)pCondItem)->GetValue(); |
| else |
| bBreak = ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue(); |
| |
| SvNumberFormatter* pFormatter = pDocument->GetFormatTable(); |
| sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet ); |
| // #i111387# #o11817313# disable automatic line breaks only for "General" number format |
| if ( bBreak && pCell->HasValueData() && ( nFormat % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 ) |
| { |
| // also take formula result type into account for number format |
| if ( pCell->GetCellType() != CELLTYPE_FORMULA || |
| ( static_cast<ScFormulaCell*>(pCell)->GetStandardFormat(*pFormatter, nFormat) % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 ) |
| bBreak = false; |
| } |
| |
| // get other attributes from pattern and conditional formatting |
| |
| SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet ); |
| sal_Bool bAsianVertical = ( eOrient == SVX_ORIENTATION_STACKED && |
| ((const SfxBoolItem&)pPattern->GetItem( ATTR_VERTICAL_ASIAN, pCondSet )).GetValue() ); |
| if ( bAsianVertical ) |
| bBreak = false; |
| |
| if ( bWidth && bBreak ) // after determining bAsianVertical (bBreak may be reset) |
| return 0; |
| |
| long nRotate = 0; |
| SvxRotateMode eRotMode = SVX_ROTATE_MODE_STANDARD; |
| if ( eOrient == SVX_ORIENTATION_STANDARD ) |
| { |
| if (pCondSet && |
| pCondSet->GetItemState(ATTR_ROTATE_VALUE, sal_True, &pCondItem) == SFX_ITEM_SET) |
| nRotate = ((const SfxInt32Item*)pCondItem)->GetValue(); |
| else |
| nRotate = ((const SfxInt32Item&)pPattern->GetItem(ATTR_ROTATE_VALUE)).GetValue(); |
| if ( nRotate ) |
| { |
| if (pCondSet && |
| pCondSet->GetItemState(ATTR_ROTATE_MODE, sal_True, &pCondItem) == SFX_ITEM_SET) |
| eRotMode = (SvxRotateMode)((const SvxRotateModeItem*)pCondItem)->GetValue(); |
| else |
| eRotMode = (SvxRotateMode)((const SvxRotateModeItem&) |
| pPattern->GetItem(ATTR_ROTATE_MODE)).GetValue(); |
| |
| if ( nRotate == 18000 ) |
| eRotMode = SVX_ROTATE_MODE_STANDARD; // keinen Ueberlauf |
| } |
| } |
| |
| if ( eHorJust == SVX_HOR_JUSTIFY_REPEAT ) |
| { |
| // ignore orientation/rotation if "repeat" is active |
| eOrient = SVX_ORIENTATION_STANDARD; |
| nRotate = 0; |
| bAsianVertical = sal_False; |
| } |
| |
| const SvxMarginItem* pMargin; |
| if (pCondSet && |
| pCondSet->GetItemState(ATTR_MARGIN, sal_True, &pCondItem) == SFX_ITEM_SET) |
| pMargin = (const SvxMarginItem*) pCondItem; |
| else |
| pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN); |
| sal_uInt16 nIndent = 0; |
| if ( eHorJust == SVX_HOR_JUSTIFY_LEFT ) |
| { |
| if (pCondSet && |
| pCondSet->GetItemState(ATTR_INDENT, sal_True, &pCondItem) == SFX_ITEM_SET) |
| nIndent = ((const SfxUInt16Item*)pCondItem)->GetValue(); |
| else |
| nIndent = ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue(); |
| } |
| |
| sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, pCell ); |
| if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType(); |
| |
| // also call SetFont for edit cells, because bGetFont may be set only once |
| // bGetFont is set also if script type changes |
| if (rOptions.bGetFont) |
| { |
| Fraction aFontZoom = ( eOrient == SVX_ORIENTATION_STANDARD ) ? rZoomX : rZoomY; |
| Font aFont; |
| // font color doesn't matter here |
| pPattern->GetFont( aFont, SC_AUTOCOL_BLACK, pDev, &aFontZoom, pCondSet, nScript ); |
| pDev->SetFont(aFont); |
| } |
| |
| sal_Bool bAddMargin = sal_True; |
| CellType eCellType = pCell->GetCellType(); |
| |
| sal_Bool bEditEngine = ( eCellType == CELLTYPE_EDIT || |
| eOrient == SVX_ORIENTATION_STACKED || |
| IsAmbiguousScript( nScript ) || |
| ((eCellType == CELLTYPE_FORMULA) && ((ScFormulaCell*)pCell)->IsMultilineResult()) ); |
| |
| if (!bEditEngine) // direkte Ausgabe |
| { |
| String aValStr; |
| Color* pColor; |
| ScCellFormat::GetString( pCell, nFormat, aValStr, &pColor, |
| *pFormatter, |
| sal_True, rOptions.bFormula, ftCheck ); |
| if (aValStr.Len()) |
| { |
| // SetFont ist nach oben verschoben |
| |
| Size aSize( pDev->GetTextWidth( aValStr ), pDev->GetTextHeight() ); |
| if ( eOrient != SVX_ORIENTATION_STANDARD ) |
| { |
| long nTemp = aSize.Width(); |
| aSize.Width() = aSize.Height(); |
| aSize.Height() = nTemp; |
| } |
| else if ( nRotate ) |
| { |
| //! unterschiedliche Skalierung X/Y beruecksichtigen |
| |
| double nRealOrient = nRotate * F_PI18000; // nRotate sind 1/100 Grad |
| double nCosAbs = fabs( cos( nRealOrient ) ); |
| double nSinAbs = fabs( sin( nRealOrient ) ); |
| long nHeight = (long)( aSize.Height() * nCosAbs + aSize.Width() * nSinAbs ); |
| long nWidth; |
| if ( eRotMode == SVX_ROTATE_MODE_STANDARD ) |
| nWidth = (long)( aSize.Width() * nCosAbs + aSize.Height() * nSinAbs ); |
| else if ( rOptions.bTotalSize ) |
| { |
| nWidth = (long) ( pDocument->GetColWidth( nCol,nTab ) * nPPT ); |
| bAddMargin = sal_False; |
| // nur nach rechts: |
| //! unterscheiden nach Ausrichtung oben/unten (nur Text/ganze Hoehe) |
| if ( pPattern->GetRotateDir( pCondSet ) == SC_ROTDIR_RIGHT ) |
| nWidth += (long)( pDocument->GetRowHeight( nRow,nTab ) * |
| nPPT * nCosAbs / nSinAbs ); |
| } |
| else |
| nWidth = (long)( aSize.Height() / nSinAbs ); //! begrenzen? |
| |
| if ( bBreak && !rOptions.bTotalSize ) |
| { |
| // #47744# limit size for line break |
| long nCmp = pDev->GetFont().GetSize().Height() * SC_ROT_BREAK_FACTOR; |
| if ( nHeight > nCmp ) |
| nHeight = nCmp; |
| } |
| |
| aSize = Size( nWidth, nHeight ); |
| } |
| nValue = bWidth ? aSize.Width() : aSize.Height(); |
| |
| if ( bAddMargin ) |
| { |
| if (bWidth) |
| { |
| nValue += (long) ( pMargin->GetLeftMargin() * nPPT ) + |
| (long) ( pMargin->GetRightMargin() * nPPT ); |
| if ( nIndent ) |
| nValue += (long) ( nIndent * nPPT ); |
| } |
| else |
| nValue += (long) ( pMargin->GetTopMargin() * nPPT ) + |
| (long) ( pMargin->GetBottomMargin() * nPPT ); |
| } |
| |
| // Zeilenumbruch ausgefuehrt ? |
| |
| if ( bBreak && !bWidth ) |
| { |
| // Test mit EditEngine zur Sicherheit schon bei 90% |
| // (wegen Rundungsfehlern und weil EditEngine teilweise anders formatiert) |
| |
| long nDocPixel = (long) ( ( pDocument->GetColWidth( nCol,nTab ) - |
| pMargin->GetLeftMargin() - pMargin->GetRightMargin() - |
| nIndent ) |
| * nPPT ); |
| nDocPixel = (nDocPixel * 9) / 10; // zur Sicherheit |
| if ( aSize.Width() > nDocPixel ) |
| bEditEngine = sal_True; |
| } |
| } |
| } |
| |
| if (bEditEngine) |
| { |
| // der Font wird bei !bEditEngine nicht jedesmal neu gesetzt |
| Font aOldFont = pDev->GetFont(); |
| |
| MapMode aHMMMode( MAP_100TH_MM, Point(), rZoomX, rZoomY ); |
| |
| // am Dokument speichern ? |
| ScFieldEditEngine* pEngine = pDocument->CreateFieldEditEngine(); |
| |
| pEngine->SetUpdateMode( sal_False ); |
| sal_Bool bTextWysiwyg = ( pDev->GetOutDevType() == OUTDEV_PRINTER ); |
| sal_uInt32 nCtrl = pEngine->GetControlWord(); |
| if ( bTextWysiwyg ) |
| nCtrl |= EE_CNTRL_FORMAT100; |
| else |
| nCtrl &= ~EE_CNTRL_FORMAT100; |
| pEngine->SetControlWord( nCtrl ); |
| MapMode aOld = pDev->GetMapMode(); |
| pDev->SetMapMode( aHMMMode ); |
| pEngine->SetRefDevice( pDev ); |
| pDocument->ApplyAsianEditSettings( *pEngine ); |
| SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() ); |
| pPattern->FillEditItemSet( pSet, pCondSet ); |
| |
| // no longer needed, are setted with the text (is faster) |
| // pEngine->SetDefaults( pSet ); |
| |
| if ( ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() ) { |
| |
| com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() ); |
| pEngine->SetHyphenator( xXHyphenator ); |
| } |
| |
| Size aPaper = Size( 1000000, 1000000 ); |
| if ( eOrient==SVX_ORIENTATION_STACKED && !bAsianVertical ) |
| aPaper.Width() = 1; |
| else if (bBreak) |
| { |
| double fWidthFactor = nPPTX; |
| if ( bTextWysiwyg ) |
| { |
| // #95593# if text is formatted for printer, don't use PixelToLogic, |
| // to ensure the exact same paper width (and same line breaks) as in |
| // ScEditUtil::GetEditArea, used for output. |
| |
| fWidthFactor = HMM_PER_TWIPS; |
| } |
| |
| // use original width for hidden columns: |
| long nDocWidth = (long) ( pDocument->GetOriginalWidth(nCol,nTab) * fWidthFactor ); |
| SCCOL nColMerge = pMerge->GetColMerge(); |
| if (nColMerge > 1) |
| for (SCCOL nColAdd=1; nColAdd<nColMerge; nColAdd++) |
| nDocWidth += (long) ( pDocument->GetColWidth(nCol+nColAdd,nTab) * fWidthFactor ); |
| nDocWidth -= (long) ( pMargin->GetLeftMargin() * fWidthFactor ) |
| + (long) ( pMargin->GetRightMargin() * fWidthFactor ) |
| + 1; // Ausgabebereich ist Breite-1 Pixel (wegen Gitterlinien) |
| if ( nIndent ) |
| nDocWidth -= (long) ( nIndent * fWidthFactor ); |
| |
| // space for AutoFilter button: 20 * nZoom/100 |
| if ( pFlag->HasAutoFilter() && !bTextWysiwyg ) |
| nDocWidth -= (rZoomX.GetNumerator()*20)/rZoomX.GetDenominator(); |
| |
| aPaper.Width() = nDocWidth; |
| |
| if ( !bTextWysiwyg ) |
| aPaper = pDev->PixelToLogic( aPaper, aHMMMode ); |
| } |
| pEngine->SetPaperSize(aPaper); |
| |
| if ( pCell->GetCellType() == CELLTYPE_EDIT ) |
| { |
| const EditTextObject* pData; |
| ((ScEditCell*)pCell)->GetData(pData); |
| pEngine->SetTextNewDefaults(*pData, pSet); |
| } |
| else |
| { |
| Color* pColor; |
| String aString; |
| ScCellFormat::GetString( pCell, nFormat, aString, &pColor, |
| *pFormatter, |
| sal_True, rOptions.bFormula, ftCheck ); |
| if (aString.Len()) |
| pEngine->SetTextNewDefaults(aString, pSet); |
| else |
| pEngine->SetDefaults(pSet); |
| } |
| |
| sal_Bool bEngineVertical = pEngine->IsVertical(); |
| pEngine->SetVertical( bAsianVertical ); |
| pEngine->SetUpdateMode( sal_True ); |
| |
| sal_Bool bEdWidth = bWidth; |
| if ( eOrient != SVX_ORIENTATION_STANDARD && eOrient != SVX_ORIENTATION_STACKED ) |
| bEdWidth = !bEdWidth; |
| if ( nRotate ) |
| { |
| //! unterschiedliche Skalierung X/Y beruecksichtigen |
| |
| Size aSize( pEngine->CalcTextWidth(), pEngine->GetTextHeight() ); |
| double nRealOrient = nRotate * F_PI18000; // nRotate sind 1/100 Grad |
| double nCosAbs = fabs( cos( nRealOrient ) ); |
| double nSinAbs = fabs( sin( nRealOrient ) ); |
| long nHeight = (long)( aSize.Height() * nCosAbs + aSize.Width() * nSinAbs ); |
| long nWidth; |
| if ( eRotMode == SVX_ROTATE_MODE_STANDARD ) |
| nWidth = (long)( aSize.Width() * nCosAbs + aSize.Height() * nSinAbs ); |
| else if ( rOptions.bTotalSize ) |
| { |
| nWidth = (long) ( pDocument->GetColWidth( nCol,nTab ) * nPPT ); |
| bAddMargin = sal_False; |
| if ( pPattern->GetRotateDir( pCondSet ) == SC_ROTDIR_RIGHT ) |
| nWidth += (long)( pDocument->GetRowHeight( nRow,nTab ) * |
| nPPT * nCosAbs / nSinAbs ); |
| } |
| else |
| nWidth = (long)( aSize.Height() / nSinAbs ); //! begrenzen? |
| aSize = Size( nWidth, nHeight ); |
| |
| Size aPixSize = pDev->LogicToPixel( aSize, aHMMMode ); |
| if ( bEdWidth ) |
| nValue = aPixSize.Width(); |
| else |
| { |
| nValue = aPixSize.Height(); |
| |
| if ( bBreak && !rOptions.bTotalSize ) |
| { |
| // #47744# limit size for line break |
| long nCmp = aOldFont.GetSize().Height() * SC_ROT_BREAK_FACTOR; |
| if ( nValue > nCmp ) |
| nValue = nCmp; |
| } |
| } |
| } |
| else if ( bEdWidth ) |
| { |
| if (bBreak) |
| nValue = 0; |
| else |
| nValue = pDev->LogicToPixel(Size( pEngine->CalcTextWidth(), 0 ), |
| aHMMMode).Width(); |
| } |
| else // Hoehe |
| { |
| nValue = pDev->LogicToPixel(Size( 0, pEngine->GetTextHeight() ), |
| aHMMMode).Height(); |
| |
| // With non-100% zoom and several lines or paragraphs, don't shrink below the result with FORMAT100 set |
| if ( !bTextWysiwyg && ( rZoomY.GetNumerator() != 1 || rZoomY.GetDenominator() != 1 ) && |
| ( pEngine->GetParagraphCount() > 1 || ( bBreak && pEngine->GetLineCount(0) > 1 ) ) ) |
| { |
| pEngine->SetControlWord( nCtrl | EE_CNTRL_FORMAT100 ); |
| pEngine->QuickFormatDoc( sal_True ); |
| long nSecondValue = pDev->LogicToPixel(Size( 0, pEngine->GetTextHeight() ), aHMMMode).Height(); |
| if ( nSecondValue > nValue ) |
| nValue = nSecondValue; |
| } |
| } |
| |
| if ( nValue && bAddMargin ) |
| { |
| if (bWidth) |
| { |
| nValue += (long) ( pMargin->GetLeftMargin() * nPPT ) + |
| (long) ( pMargin->GetRightMargin() * nPPT ); |
| if (nIndent) |
| nValue += (long) ( nIndent * nPPT ); |
| } |
| else |
| { |
| nValue += (long) ( pMargin->GetTopMargin() * nPPT ) + |
| (long) ( pMargin->GetBottomMargin() * nPPT ); |
| |
| if ( bAsianVertical && pDev->GetOutDevType() != OUTDEV_PRINTER ) |
| { |
| // add 1pt extra (default margin value) for line breaks with SetVertical |
| nValue += (long) ( 20 * nPPT ); |
| } |
| } |
| } |
| |
| // EditEngine is cached and re-used, so the old vertical flag must be restored |
| pEngine->SetVertical( bEngineVertical ); |
| |
| pDocument->DisposeFieldEditEngine(pEngine); |
| |
| pDev->SetMapMode( aOld ); |
| pDev->SetFont( aOldFont ); |
| } |
| |
| if (bWidth) |
| { |
| // Platz fuer Autofilter-Button |
| // 20 * nZoom/100 |
| // bedingte Formatierung hier nicht interessant |
| |
| sal_Int16 nFlags = ((const ScMergeFlagAttr&)pPattern->GetItem(ATTR_MERGE_FLAG)).GetValue(); |
| if (nFlags & SC_MF_AUTO) |
| nValue += (rZoomX.GetNumerator()*20)/rZoomX.GetDenominator(); |
| } |
| } |
| return nValue; |
| } |
| |
| long ScColumn::GetSimpleTextNeededSize( SCSIZE nIndex, OutputDevice* pDev, |
| sal_Bool bWidth ) |
| { |
| long nValue=0; |
| if ( nIndex < nCount ) |
| { |
| SCROW nRow = pItems[nIndex].nRow; |
| const ScPatternAttr* pPattern = pAttrArray->GetPattern( nRow ); |
| ScBaseCell* pCell = pItems[nIndex].pCell; |
| String aValStr; |
| Color* pColor; |
| SvNumberFormatter* pFormatter = pDocument->GetFormatTable(); |
| sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter ); |
| ScCellFormat::GetString( pCell, nFormat, aValStr, &pColor, |
| *pFormatter, sal_True, sal_False, ftCheck ); |
| if ( aValStr.Len() ) |
| { |
| if ( bWidth ) |
| nValue = pDev->GetTextWidth( aValStr ); |
| else |
| nValue = pDev->GetTextHeight(); |
| } |
| } |
| return nValue; |
| } |
| |
| sal_uInt16 ScColumn::GetOptimalColWidth( OutputDevice* pDev, double nPPTX, double nPPTY, |
| const Fraction& rZoomX, const Fraction& rZoomY, |
| sal_Bool bFormula, sal_uInt16 nOldWidth, |
| const ScMarkData* pMarkData, |
| sal_Bool bSimpleTextImport ) |
| { |
| if (nCount == 0) |
| return nOldWidth; |
| |
| sal_uInt16 nWidth = (sal_uInt16) (nOldWidth * nPPTX); |
| sal_Bool bFound = sal_False; |
| |
| SCSIZE nIndex; |
| ScMarkedDataIter aDataIter(this, pMarkData, sal_True); |
| if ( bSimpleTextImport ) |
| { // alles eins bis auf NumberFormate |
| const ScPatternAttr* pPattern = GetPattern( 0 ); |
| Font aFont; |
| // font color doesn't matter here |
| pPattern->GetFont( aFont, SC_AUTOCOL_BLACK, pDev, &rZoomX, NULL ); |
| pDev->SetFont( aFont ); |
| const SvxMarginItem* pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN); |
| long nMargin = (long) ( pMargin->GetLeftMargin() * nPPTX ) + |
| (long) ( pMargin->GetRightMargin() * nPPTX ); |
| |
| while (aDataIter.Next( nIndex )) |
| { |
| sal_uInt16 nThis = (sal_uInt16) (GetSimpleTextNeededSize( nIndex, pDev, |
| sal_True ) + nMargin); |
| if (nThis) |
| { |
| if (nThis>nWidth || !bFound) |
| { |
| nWidth = nThis; |
| bFound = sal_True; |
| } |
| } |
| } |
| } |
| else |
| { |
| ScNeededSizeOptions aOptions; |
| aOptions.bFormula = bFormula; |
| const ScPatternAttr* pOldPattern = NULL; |
| sal_uInt8 nOldScript = 0; |
| |
| while (aDataIter.Next( nIndex )) |
| { |
| SCROW nRow = pItems[nIndex].nRow; |
| |
| sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, pItems[nIndex].pCell ); |
| if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType(); |
| |
| const ScPatternAttr* pPattern = GetPattern( nRow ); |
| aOptions.pPattern = pPattern; |
| aOptions.bGetFont = (pPattern != pOldPattern || nScript != nOldScript); |
| sal_uInt16 nThis = (sal_uInt16) GetNeededSize( nRow, pDev, nPPTX, nPPTY, |
| rZoomX, rZoomY, sal_True, aOptions ); |
| pOldPattern = pPattern; |
| if (nThis) |
| { |
| if (nThis>nWidth || !bFound) |
| { |
| nWidth = nThis; |
| bFound = sal_True; |
| } |
| } |
| } |
| } |
| |
| if (bFound) |
| { |
| nWidth += 2; |
| sal_uInt16 nTwips = (sal_uInt16) (nWidth / nPPTX); |
| return nTwips; |
| } |
| else |
| return nOldWidth; |
| } |
| |
| sal_uInt16 lcl_GetAttribHeight( const ScPatternAttr& rPattern, sal_uInt16 nFontHeightId ) |
| { |
| sal_uInt16 nHeight = (sal_uInt16) ((const SvxFontHeightItem&) rPattern.GetItem(nFontHeightId)).GetHeight(); |
| const SvxMarginItem* pMargin = (const SvxMarginItem*) &rPattern.GetItem(ATTR_MARGIN); |
| nHeight += nHeight / 5; |
| // gibt bei 10pt 240 |
| |
| if ( ((const SvxEmphasisMarkItem&)rPattern. |
| GetItem(ATTR_FONT_EMPHASISMARK)).GetEmphasisMark() != EMPHASISMARK_NONE ) |
| { |
| // add height for emphasis marks |
| //! font metrics should be used instead |
| nHeight += nHeight / 4; |
| } |
| |
| if ( nHeight + 240 > ScGlobal::nDefFontHeight ) |
| { |
| nHeight = sal::static_int_cast<sal_uInt16>( nHeight + ScGlobal::nDefFontHeight ); |
| nHeight -= 240; |
| } |
| |
| // Standard-Hoehe: TextHeight + Raender - 23 |
| // -> 257 unter Windows |
| |
| if (nHeight > STD_ROWHEIGHT_DIFF) |
| nHeight -= STD_ROWHEIGHT_DIFF; |
| |
| nHeight += pMargin->GetTopMargin() + pMargin->GetBottomMargin(); |
| |
| return nHeight; |
| } |
| |
| // pHeight in Twips |
| // nMinHeight, nMinStart zur Optimierung: ab nRow >= nMinStart ist mindestens nMinHeight |
| // (wird nur bei bStdAllowed ausgewertet) |
| |
| void ScColumn::GetOptimalHeight( SCROW nStartRow, SCROW nEndRow, sal_uInt16* pHeight, |
| OutputDevice* pDev, |
| double nPPTX, double nPPTY, |
| const Fraction& rZoomX, const Fraction& rZoomY, |
| sal_Bool bShrink, sal_uInt16 nMinHeight, SCROW nMinStart ) |
| { |
| ScAttrIterator aIter( pAttrArray, nStartRow, nEndRow ); |
| |
| SCROW nStart = -1; |
| SCROW nEnd = -1; |
| SCROW nEditPos = 0; |
| SCROW nNextEnd = 0; |
| |
| // bei bedingter Formatierung werden immer die einzelnen Zellen angesehen |
| |
| const ScPatternAttr* pPattern = aIter.Next(nStart,nEnd); |
| while ( pPattern ) |
| { |
| const ScMergeAttr* pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE); |
| const ScMergeFlagAttr* pFlag = (const ScMergeFlagAttr*)&pPattern->GetItem(ATTR_MERGE_FLAG); |
| if ( pMerge->GetRowMerge() > 1 || pFlag->IsOverlapped() ) |
| { |
| // nix - vertikal bei der zusammengefassten und den ueberdeckten, |
| // horizontal nur bei den ueberdeckten (unsichtbaren) - |
| // eine nur horizontal zusammengefasste wird aber beruecksichtigt |
| } |
| else |
| { |
| SCROW nRow = 0; |
| sal_Bool bStdAllowed = (pPattern->GetCellOrientation() == SVX_ORIENTATION_STANDARD); |
| sal_Bool bStdOnly = sal_False; |
| if (bStdAllowed) |
| { |
| sal_Bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() || |
| ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern-> |
| GetItem( ATTR_HOR_JUSTIFY )).GetValue() == |
| SVX_HOR_JUSTIFY_BLOCK); |
| bStdOnly = !bBreak; |
| |
| // bedingte Formatierung: Zellen durchgehen |
| if ( bStdOnly && ((const SfxUInt32Item&)pPattern-> |
| GetItem(ATTR_CONDITIONAL)).GetValue() ) |
| bStdOnly = sal_False; |
| |
| // gedrehter Text: Zellen durchgehen |
| if ( bStdOnly && ((const SfxInt32Item&)pPattern-> |
| GetItem(ATTR_ROTATE_VALUE)).GetValue() ) |
| bStdOnly = sal_False; |
| } |
| |
| if (bStdOnly) |
| if (HasEditCells(nStart,nEnd,nEditPos)) // includes mixed script types |
| { |
| if (nEditPos == nStart) |
| { |
| bStdOnly = sal_False; |
| if (nEnd > nEditPos) |
| nNextEnd = nEnd; |
| nEnd = nEditPos; // einzeln ausrechnen |
| bStdAllowed = sal_False; // wird auf jeden Fall per Zelle berechnet |
| } |
| else |
| { |
| nNextEnd = nEnd; |
| nEnd = nEditPos - 1; // Standard - Teil |
| } |
| } |
| |
| if (bStdAllowed) |
| { |
| sal_uInt16 nLatHeight = 0; |
| sal_uInt16 nCjkHeight = 0; |
| sal_uInt16 nCtlHeight = 0; |
| sal_uInt16 nDefHeight; |
| sal_uInt8 nDefScript = ScGlobal::GetDefaultScriptType(); |
| if ( nDefScript == SCRIPTTYPE_ASIAN ) |
| nDefHeight = nCjkHeight = lcl_GetAttribHeight( *pPattern, ATTR_CJK_FONT_HEIGHT ); |
| else if ( nDefScript == SCRIPTTYPE_COMPLEX ) |
| nDefHeight = nCtlHeight = lcl_GetAttribHeight( *pPattern, ATTR_CTL_FONT_HEIGHT ); |
| else |
| nDefHeight = nLatHeight = lcl_GetAttribHeight( *pPattern, ATTR_FONT_HEIGHT ); |
| |
| // if everything below is already larger, the loop doesn't have to |
| // be run again |
| SCROW nStdEnd = nEnd; |
| if ( nDefHeight <= nMinHeight && nStdEnd >= nMinStart ) |
| nStdEnd = (nMinStart>0) ? nMinStart-1 : 0; |
| |
| for (nRow=nStart; nRow<=nStdEnd; nRow++) |
| if (nDefHeight > pHeight[nRow-nStartRow]) |
| pHeight[nRow-nStartRow] = nDefHeight; |
| |
| if ( bStdOnly ) |
| { |
| // if cells are not handled individually below, |
| // check for cells with different script type |
| |
| SCSIZE nIndex; |
| Search(nStart,nIndex); |
| while ( nIndex < nCount && (nRow=pItems[nIndex].nRow) <= nEnd ) |
| { |
| sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, pItems[nIndex].pCell ); |
| if ( nScript != nDefScript ) |
| { |
| if ( nScript == SCRIPTTYPE_ASIAN ) |
| { |
| if ( nCjkHeight == 0 ) |
| nCjkHeight = lcl_GetAttribHeight( *pPattern, ATTR_CJK_FONT_HEIGHT ); |
| if (nCjkHeight > pHeight[nRow-nStartRow]) |
| pHeight[nRow-nStartRow] = nCjkHeight; |
| } |
| else if ( nScript == SCRIPTTYPE_COMPLEX ) |
| { |
| if ( nCtlHeight == 0 ) |
| nCtlHeight = lcl_GetAttribHeight( *pPattern, ATTR_CTL_FONT_HEIGHT ); |
| if (nCtlHeight > pHeight[nRow-nStartRow]) |
| pHeight[nRow-nStartRow] = nCtlHeight; |
| } |
| else |
| { |
| if ( nLatHeight == 0 ) |
| nLatHeight = lcl_GetAttribHeight( *pPattern, ATTR_FONT_HEIGHT ); |
| if (nLatHeight > pHeight[nRow-nStartRow]) |
| pHeight[nRow-nStartRow] = nLatHeight; |
| } |
| } |
| ++nIndex; |
| } |
| } |
| } |
| |
| if (!bStdOnly) // belegte Zellen suchen |
| { |
| ScNeededSizeOptions aOptions; |
| |
| SCSIZE nIndex; |
| Search(nStart,nIndex); |
| while ( (nIndex < nCount) ? ((nRow=pItems[nIndex].nRow) <= nEnd) : sal_False ) |
| { |
| // Zellhoehe nur berechnen, wenn sie spaeter auch gebraucht wird (#37928#) |
| |
| if ( bShrink || !(pDocument->GetRowFlags(nRow, nTab) & CR_MANUALSIZE) ) |
| { |
| aOptions.pPattern = pPattern; |
| sal_uInt16 nHeight = (sal_uInt16) |
| ( GetNeededSize( nRow, pDev, nPPTX, nPPTY, |
| rZoomX, rZoomY, sal_False, aOptions ) / nPPTY ); |
| if (nHeight > pHeight[nRow-nStartRow]) |
| pHeight[nRow-nStartRow] = nHeight; |
| } |
| ++nIndex; |
| } |
| } |
| } |
| |
| if (nNextEnd > 0) |
| { |
| nStart = nEnd + 1; |
| nEnd = nNextEnd; |
| nNextEnd = 0; |
| } |
| else |
| pPattern = aIter.Next(nStart,nEnd); |
| } |
| } |
| |
| sal_Bool ScColumn::GetNextSpellingCell(SCROW& nRow, sal_Bool bInSel, const ScMarkData& rData) const |
| { |
| sal_Bool bStop = sal_False; |
| CellType eCellType; |
| SCSIZE nIndex; |
| if (!bInSel && Search(nRow, nIndex)) |
| { |
| eCellType = GetCellType(nRow); |
| if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) && |
| !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) && |
| pDocument->IsTabProtected(nTab)) ) |
| return sal_True; |
| } |
| while (!bStop) |
| { |
| if (bInSel) |
| { |
| nRow = rData.GetNextMarked(nCol, nRow, sal_False); |
| if (!ValidRow(nRow)) |
| { |
| nRow = MAXROW+1; |
| bStop = sal_True; |
| } |
| else |
| { |
| eCellType = GetCellType(nRow); |
| if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) && |
| !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) && |
| pDocument->IsTabProtected(nTab)) ) |
| return sal_True; |
| else |
| nRow++; |
| } |
| } |
| else if (GetNextDataPos(nRow)) |
| { |
| eCellType = GetCellType(nRow); |
| if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) && |
| !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) && |
| pDocument->IsTabProtected(nTab)) ) |
| return sal_True; |
| else |
| nRow++; |
| } |
| else |
| { |
| nRow = MAXROW+1; |
| bStop = sal_True; |
| } |
| } |
| return sal_False; |
| } |
| |
| // ========================================================================================= |
| |
| void ScColumn::RemoveAutoSpellObj() |
| { |
| ScTabEditEngine* pEngine = NULL; |
| |
| for (SCSIZE i=0; i<nCount; i++) |
| if ( pItems[i].pCell->GetCellType() == CELLTYPE_EDIT ) |
| { |
| ScEditCell* pOldCell = (ScEditCell*) pItems[i].pCell; |
| const EditTextObject* pData = pOldCell->GetData(); |
| // keine Abfrage auf HasOnlineSpellErrors, damit es auch |
| // nach dem Laden funktioniert |
| |
| // Fuer den Test auf harte Formatierung (ScEditAttrTester) sind die Defaults |
| // in der EditEngine unwichtig. Wenn der Tester spaeter einmal gleiche |
| // Attribute in Default und harter Formatierung erkennen und weglassen sollte, |
| // muessten an der EditEngine zu jeder Zelle die richtigen Defaults gesetzt |
| // werden! |
| |
| // auf Attribute testen |
| if ( !pEngine ) |
| pEngine = new ScTabEditEngine(pDocument); |
| pEngine->SetText( *pData ); |
| ScEditAttrTester aTester( pEngine ); |
| if ( aTester.NeedsObject() ) // nur Spell-Errors entfernen |
| { |
| EditTextObject* pNewData = pEngine->CreateTextObject(); // ohne BIGOBJ |
| pOldCell->SetData( pNewData, pEngine->GetEditTextObjectPool() ); |
| delete pNewData; |
| } |
| else // String erzeugen |
| { |
| String aText = ScEditUtil::GetSpaceDelimitedString( *pEngine ); |
| ScBaseCell* pNewCell = new ScStringCell( aText ); |
| pNewCell->TakeBroadcaster( pOldCell->ReleaseBroadcaster() ); |
| pNewCell->TakeNote( pOldCell->ReleaseNote() ); |
| pItems[i].pCell = pNewCell; |
| delete pOldCell; |
| } |
| } |
| |
| delete pEngine; |
| } |
| |
| void ScColumn::RemoveEditAttribs( SCROW nStartRow, SCROW nEndRow ) |
| { |
| ScFieldEditEngine* pEngine = NULL; |
| |
| SCSIZE i; |
| Search( nStartRow, i ); |
| for (; i<nCount && pItems[i].nRow <= nEndRow; i++) |
| if ( pItems[i].pCell->GetCellType() == CELLTYPE_EDIT ) |
| { |
| ScEditCell* pOldCell = (ScEditCell*) pItems[i].pCell; |
| const EditTextObject* pData = pOldCell->GetData(); |
| |
| // Fuer den Test auf harte Formatierung (ScEditAttrTester) sind die Defaults |
| // in der EditEngine unwichtig. Wenn der Tester spaeter einmal gleiche |
| // Attribute in Default und harter Formatierung erkennen und weglassen sollte, |
| // muessten an der EditEngine zu jeder Zelle die richtigen Defaults gesetzt |
| // werden! |
| |
| // auf Attribute testen |
| if ( !pEngine ) |
| { |
| //pEngine = new ScTabEditEngine(pDocument); |
| pEngine = new ScFieldEditEngine( pDocument->GetEditPool() ); |
| // EE_CNTRL_ONLINESPELLING falls schon Fehler drin sind |
| pEngine->SetControlWord( pEngine->GetControlWord() | EE_CNTRL_ONLINESPELLING ); |
| pDocument->ApplyAsianEditSettings( *pEngine ); |
| } |
| pEngine->SetText( *pData ); |
| sal_uInt16 nParCount = pEngine->GetParagraphCount(); |
| for (sal_uInt16 nPar=0; nPar<nParCount; nPar++) |
| { |
| pEngine->QuickRemoveCharAttribs( nPar ); |
| const SfxItemSet& rOld = pEngine->GetParaAttribs( nPar ); |
| if ( rOld.Count() ) |
| { |
| SfxItemSet aNew( *rOld.GetPool(), rOld.GetRanges() ); // leer |
| pEngine->SetParaAttribs( nPar, aNew ); |
| } |
| } |
| // URL-Felder in Text wandeln (andere gibt's nicht, darum pType=0) |
| pEngine->RemoveFields( sal_True ); |
| |
| sal_Bool bSpellErrors = pEngine->HasOnlineSpellErrors(); |
| sal_Bool bNeedObject = bSpellErrors || nParCount>1; // Errors/Absaetze behalten |
| // ScEditAttrTester nicht mehr noetig, Felder sind raus |
| |
| if ( bNeedObject ) // bleibt Edit-Zelle |
| { |
| sal_uLong nCtrl = pEngine->GetControlWord(); |
| sal_uLong nWantBig = bSpellErrors ? EE_CNTRL_ALLOWBIGOBJS : 0; |
| if ( ( nCtrl & EE_CNTRL_ALLOWBIGOBJS ) != nWantBig ) |
| pEngine->SetControlWord( (nCtrl & ~EE_CNTRL_ALLOWBIGOBJS) | nWantBig ); |
| EditTextObject* pNewData = pEngine->CreateTextObject(); |
| pOldCell->SetData( pNewData, pEngine->GetEditTextObjectPool() ); |
| delete pNewData; |
| } |
| else // String erzeugen |
| { |
| String aText = ScEditUtil::GetSpaceDelimitedString( *pEngine ); |
| ScBaseCell* pNewCell = new ScStringCell( aText ); |
| pNewCell->TakeBroadcaster( pOldCell->ReleaseBroadcaster() ); |
| pNewCell->TakeNote( pOldCell->ReleaseNote() ); |
| pItems[i].pCell = pNewCell; |
| delete pOldCell; |
| } |
| } |
| |
| delete pEngine; |
| } |
| |
| // ========================================================================================= |
| |
| sal_Bool ScColumn::TestTabRefAbs(SCTAB nTable) |
| { |
| sal_Bool bRet = sal_False; |
| if (pItems) |
| for (SCSIZE i = 0; i < nCount; i++) |
| if ( pItems[i].pCell->GetCellType() == CELLTYPE_FORMULA ) |
| if (((ScFormulaCell*)pItems[i].pCell)->TestTabRefAbs(nTable)) |
| bRet = sal_True; |
| return bRet; |
| } |
| |
| // ========================================================================================= |
| |
| ScColumnIterator::ScColumnIterator( const ScColumn* pCol, SCROW nStart, SCROW nEnd ) : |
| pColumn( pCol ), |
| nTop( nStart ), |
| nBottom( nEnd ) |
| { |
| pColumn->Search( nTop, nPos ); |
| } |
| |
| ScColumnIterator::~ScColumnIterator() |
| { |
| } |
| |
| sal_Bool ScColumnIterator::Next( SCROW& rRow, ScBaseCell*& rpCell ) |
| { |
| if ( nPos < pColumn->nCount ) |
| { |
| rRow = pColumn->pItems[nPos].nRow; |
| if ( rRow <= nBottom ) |
| { |
| rpCell = pColumn->pItems[nPos].pCell; |
| ++nPos; |
| return sal_True; |
| } |
| } |
| |
| rRow = 0; |
| rpCell = NULL; |
| return sal_False; |
| } |
| |
| SCSIZE ScColumnIterator::GetIndex() const // Index zur letzen abgefragten Zelle |
| { |
| return nPos - 1; // bei Next ist Pos hochgezaehlt worden |
| } |
| |
| // ----------------------------------------------------------------------------------------- |
| |
| ScMarkedDataIter::ScMarkedDataIter( const ScColumn* pCol, const ScMarkData* pMarkData, |
| sal_Bool bAllIfNone ) : |
| pColumn( pCol ), |
| pMarkIter( NULL ), |
| bNext( sal_True ), |
| bAll( bAllIfNone ) |
| { |
| if (pMarkData && pMarkData->IsMultiMarked()) |
| pMarkIter = new ScMarkArrayIter( pMarkData->GetArray() + pCol->GetCol() ); |
| } |
| |
| ScMarkedDataIter::~ScMarkedDataIter() |
| { |
| delete pMarkIter; |
| } |
| |
| sal_Bool ScMarkedDataIter::Next( SCSIZE& rIndex ) |
| { |
| sal_Bool bFound = sal_False; |
| do |
| { |
| if (bNext) |
| { |
| if (!pMarkIter || !pMarkIter->Next( nTop, nBottom )) |
| { |
| if (bAll) // ganze Spalte |
| { |
| nTop = 0; |
| nBottom = MAXROW; |
| } |
| else |
| return sal_False; |
| } |
| pColumn->Search( nTop, nPos ); |
| bNext = sal_False; |
| bAll = sal_False; // nur beim ersten Versuch |
| } |
| |
| if ( nPos >= pColumn->nCount ) |
| return sal_False; |
| |
| if ( pColumn->pItems[nPos].nRow <= nBottom ) |
| bFound = sal_True; |
| else |
| bNext = sal_True; |
| } |
| while (!bFound); |
| |
| rIndex = nPos++; |
| return sal_True; |
| } |
| |
| //UNUSED2009-05 sal_uInt16 ScColumn::GetErrorData( SCROW nRow ) const |
| //UNUSED2009-05 { |
| //UNUSED2009-05 SCSIZE nIndex; |
| //UNUSED2009-05 if (Search(nRow, nIndex)) |
| //UNUSED2009-05 { |
| //UNUSED2009-05 ScBaseCell* pCell = pItems[nIndex].pCell; |
| //UNUSED2009-05 switch (pCell->GetCellType()) |
| //UNUSED2009-05 { |
| //UNUSED2009-05 case CELLTYPE_FORMULA : |
| //UNUSED2009-05 return ((ScFormulaCell*)pCell)->GetErrCode(); |
| //UNUSED2009-05 // break; |
| //UNUSED2009-05 default: |
| //UNUSED2009-05 return 0; |
| //UNUSED2009-05 } |
| //UNUSED2009-05 } |
| //UNUSED2009-05 return 0; |
| //UNUSED2009-05 } |
| |
| //------------ |
| |
| sal_Bool ScColumn::IsEmptyData() const |
| { |
| return (nCount == 0); |
| } |
| |
| sal_Bool ScColumn::IsEmptyVisData(sal_Bool bNotes) const |
| { |
| if (!pItems || nCount == 0) |
| return sal_True; |
| else |
| { |
| sal_Bool bVisData = sal_False; |
| SCSIZE i; |
| for (i=0; i<nCount && !bVisData; i++) |
| { |
| ScBaseCell* pCell = pItems[i].pCell; |
| if ( pCell->GetCellType() != CELLTYPE_NOTE || (bNotes && pCell->HasNote()) ) |
| bVisData = sal_True; |
| } |
| return !bVisData; |
| } |
| } |
| |
| SCSIZE ScColumn::VisibleCount( SCROW nStartRow, SCROW nEndRow ) const |
| { |
| // Notizen werden nicht mitgezaehlt |
| |
| SCSIZE nVisCount = 0; |
| SCSIZE nIndex; |
| Search( nStartRow, nIndex ); |
| while ( nIndex < nCount && pItems[nIndex].nRow <= nEndRow ) |
| { |
| if ( pItems[nIndex].nRow >= nStartRow && |
| pItems[nIndex].pCell->GetCellType() != CELLTYPE_NOTE ) |
| { |
| ++nVisCount; |
| } |
| ++nIndex; |
| } |
| return nVisCount; |
| } |
| |
| SCROW ScColumn::GetLastVisDataPos(sal_Bool bNotes) const |
| { |
| SCROW nRet = 0; |
| if (pItems) |
| { |
| SCSIZE i; |
| sal_Bool bFound = sal_False; |
| for (i=nCount; i>0 && !bFound; ) |
| { |
| --i; |
| ScBaseCell* pCell = pItems[i].pCell; |
| if ( pCell->GetCellType() != CELLTYPE_NOTE || (bNotes && pCell->HasNote()) ) |
| { |
| bFound = sal_True; |
| nRet = pItems[i].nRow; |
| } |
| } |
| } |
| return nRet; |
| } |
| |
| SCROW ScColumn::GetFirstVisDataPos(sal_Bool bNotes) const |
| { |
| SCROW nRet = 0; |
| if (pItems) |
| { |
| SCSIZE i; |
| sal_Bool bFound = sal_False; |
| for (i=0; i<nCount && !bFound; i++) |
| { |
| ScBaseCell* pCell = pItems[i].pCell; |
| if ( pCell->GetCellType() != CELLTYPE_NOTE || (bNotes && pCell->HasNote()) ) |
| { |
| bFound = sal_True; |
| nRet = pItems[i].nRow; |
| } |
| } |
| } |
| return nRet; |
| } |
| |
| sal_Bool ScColumn::HasVisibleDataAt(SCROW nRow) const |
| { |
| SCSIZE nIndex; |
| if (Search(nRow, nIndex)) |
| if (!pItems[nIndex].pCell->IsBlank()) |
| return sal_True; |
| |
| return sal_False; |
| } |
| |
| sal_Bool ScColumn::IsEmptyAttr() const |
| { |
| if (pAttrArray) |
| return pAttrArray->IsEmpty(); |
| else |
| return sal_True; |
| } |
| |
| sal_Bool ScColumn::IsEmpty() const |
| { |
| return (IsEmptyData() && IsEmptyAttr()); |
| } |
| |
| sal_Bool ScColumn::IsEmptyBlock(SCROW nStartRow, SCROW nEndRow, bool bIgnoreNotes) const |
| { |
| if ( nCount == 0 || !pItems ) |
| return sal_True; |
| |
| SCSIZE nIndex; |
| Search( nStartRow, nIndex ); |
| while ( nIndex < nCount && pItems[nIndex].nRow <= nEndRow ) |
| { |
| if ( !pItems[nIndex].pCell->IsBlank( bIgnoreNotes ) ) // found a cell |
| return sal_False; // not empty |
| ++nIndex; |
| } |
| return sal_True; // no cell found |
| } |
| |
| SCSIZE ScColumn::GetEmptyLinesInBlock( SCROW nStartRow, SCROW nEndRow, ScDirection eDir ) const |
| { |
| SCSIZE nLines = 0; |
| sal_Bool bFound = sal_False; |
| SCSIZE i; |
| if (pItems && (nCount > 0)) |
| { |
| if (eDir == DIR_BOTTOM) |
| { |
| i = nCount; |
| while (!bFound && (i > 0)) |
| { |
| i--; |
| if ( pItems[i].nRow < nStartRow ) |
| break; |
| bFound = pItems[i].nRow <= nEndRow && !pItems[i].pCell->IsBlank(); |
| } |
| if (bFound) |
| nLines = static_cast<SCSIZE>(nEndRow - pItems[i].nRow); |
| else |
| nLines = static_cast<SCSIZE>(nEndRow - nStartRow); |
| } |
| else if (eDir == DIR_TOP) |
| { |
| i = 0; |
| while (!bFound && (i < nCount)) |
| { |
| if ( pItems[i].nRow > nEndRow ) |
| break; |
| bFound = pItems[i].nRow >= nStartRow && !pItems[i].pCell->IsBlank(); |
| i++; |
| } |
| if (bFound) |
| nLines = static_cast<SCSIZE>(pItems[i-1].nRow - nStartRow); |
| else |
| nLines = static_cast<SCSIZE>(nEndRow - nStartRow); |
| } |
| } |
| else |
| nLines = static_cast<SCSIZE>(nEndRow - nStartRow); |
| return nLines; |
| } |
| |
| SCROW ScColumn::GetFirstDataPos() const |
| { |
| if (nCount) |
| return pItems[0].nRow; |
| else |
| return 0; |
| } |
| |
| SCROW ScColumn::GetLastDataPos() const |
| { |
| if (nCount) |
| return pItems[nCount-1].nRow; |
| else |
| return 0; |
| } |
| |
| sal_Bool ScColumn::GetPrevDataPos(SCROW& rRow) const |
| { |
| sal_Bool bFound = sal_False; |
| SCSIZE i = nCount; |
| while (!bFound && (i > 0)) |
| { |
| --i; |
| bFound = (pItems[i].nRow < rRow); |
| if (bFound) |
| rRow = pItems[i].nRow; |
| } |
| return bFound; |
| } |
| |
| sal_Bool ScColumn::GetNextDataPos(SCROW& rRow) const // greater than rRow |
| { |
| SCSIZE nIndex; |
| if (Search( rRow, nIndex )) |
| ++nIndex; // next cell |
| |
| sal_Bool bMore = ( nIndex < nCount ); |
| if ( bMore ) |
| rRow = pItems[nIndex].nRow; |
| return bMore; |
| } |
| |
| void ScColumn::FindDataAreaPos(SCROW& rRow, long nMovY) const |
| { |
| if (!nMovY) return; |
| sal_Bool bForward = (nMovY>0); |
| |
| SCSIZE nIndex; |
| sal_Bool bThere = Search(rRow, nIndex); |
| if (bThere && pItems[nIndex].pCell->IsBlank()) |
| bThere = sal_False; |
| |
| if (bThere) |
| { |
| SCROW nLast = rRow; |
| SCSIZE nOldIndex = nIndex; |
| if (bForward) |
| { |
| if (nIndex<nCount-1) |
| { |
| ++nIndex; |
| while (nIndex<nCount-1 && pItems[nIndex].nRow==nLast+1 |
| && !pItems[nIndex].pCell->IsBlank()) |
| { |
| ++nIndex; |
| ++nLast; |
| } |
| if (nIndex==nCount-1) |
| if (pItems[nIndex].nRow==nLast+1 && !pItems[nIndex].pCell->IsBlank()) |
| ++nLast; |
| } |
| } |
| else |
| { |
| if (nIndex>0) |
| { |
| --nIndex; |
| while (nIndex>0 && pItems[nIndex].nRow+1==nLast |
| && !pItems[nIndex].pCell->IsBlank()) |
| { |
| --nIndex; |
| --nLast; |
| } |
| if (nIndex==0) |
| if (pItems[nIndex].nRow+1==nLast && !pItems[nIndex].pCell->IsBlank()) |
| --nLast; |
| } |
| } |
| if (nLast==rRow) |
| { |
| bThere = sal_False; |
| nIndex = bForward ? nOldIndex+1 : nOldIndex; |
| } |
| else |
| rRow = nLast; |
| } |
| |
| if (!bThere) |
| { |
| if (bForward) |
| { |
| while (nIndex<nCount && pItems[nIndex].pCell->IsBlank()) |
| ++nIndex; |
| if (nIndex<nCount) |
| rRow = pItems[nIndex].nRow; |
| else |
| rRow = MAXROW; |
| } |
| else |
| { |
| while (nIndex>0 && pItems[nIndex-1].pCell->IsBlank()) |
| --nIndex; |
| if (nIndex>0) |
| rRow = pItems[nIndex-1].nRow; |
| else |
| rRow = 0; |
| } |
| } |
| } |
| |
| sal_Bool ScColumn::HasDataAt(SCROW nRow) const |
| { |
| /* SCSIZE nIndex; |
| return Search( nRow, nIndex ); |
| */ |
| // immer nur sichtbare interessant ? |
| //! dann HasVisibleDataAt raus |
| |
| SCSIZE nIndex; |
| if (Search(nRow, nIndex)) |
| if (!pItems[nIndex].pCell->IsBlank()) |
| return sal_True; |
| |
| return sal_False; |
| |
| } |
| |
| sal_Bool ScColumn::IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const |
| { |
| if (pAttrArray && rCol.pAttrArray) |
| return pAttrArray->IsAllEqual( *rCol.pAttrArray, nStartRow, nEndRow ); |
| else |
| return !pAttrArray && !rCol.pAttrArray; |
| } |
| |
| sal_Bool ScColumn::IsVisibleAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const |
| { |
| if (pAttrArray && rCol.pAttrArray) |
| return pAttrArray->IsVisibleEqual( *rCol.pAttrArray, nStartRow, nEndRow ); |
| else |
| return !pAttrArray && !rCol.pAttrArray; |
| } |
| |
| sal_Bool ScColumn::GetFirstVisibleAttr( SCROW& rFirstRow ) const |
| { |
| if (pAttrArray) |
| return pAttrArray->GetFirstVisibleAttr( rFirstRow ); |
| else |
| return sal_False; |
| } |
| |
| sal_Bool ScColumn::GetLastVisibleAttr( SCROW& rLastRow ) const |
| { |
| if (pAttrArray) |
| { |
| // row of last cell is needed |
| SCROW nLastData = GetLastVisDataPos( sal_True ); // always including notes, 0 if none |
| |
| return pAttrArray->GetLastVisibleAttr( rLastRow, nLastData ); |
| } |
| else |
| return sal_False; |
| } |
| |
| sal_Bool ScColumn::GetLastAttr( SCROW& rLastRow ) const |
| { |
| if ( pAttrArray ) |
| { |
| // Row of last cell is needed, always including notes, 0 if none. |
| SCROW nLastData = GetLastVisDataPos( sal_True ); |
| return pAttrArray->GetLastAttr( rLastRow, nLastData ); |
| } |
| else |
| { |
| return sal_False; |
| } |
| } |
| sal_Bool ScColumn::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const |
| { |
| if (pAttrArray) |
| return pAttrArray->HasVisibleAttrIn( nStartRow, nEndRow ); |
| else |
| return sal_False; |
| } |
| |
| void ScColumn::FindUsed( SCROW nStartRow, SCROW nEndRow, sal_Bool* pUsed ) const |
| { |
| SCROW nRow = 0; |
| SCSIZE nIndex; |
| Search( nStartRow, nIndex ); |
| while ( (nIndex < nCount) ? ((nRow=pItems[nIndex].nRow) <= nEndRow) : sal_False ) |
| { |
| pUsed[nRow-nStartRow] = sal_True; |
| ++nIndex; |
| } |
| } |
| |
| void ScColumn::StartListening( SvtListener& rLst, SCROW nRow ) |
| { |
| SvtBroadcaster* pBC = NULL; |
| ScBaseCell* pCell; |
| |
| SCSIZE nIndex; |
| if (Search(nRow,nIndex)) |
| { |
| pCell = pItems[nIndex].pCell; |
| pBC = pCell->GetBroadcaster(); |
| } |
| else |
| { |
| pCell = new ScNoteCell; |
| Insert(nRow, pCell); |
| } |
| |
| if (!pBC) |
| { |
| pBC = new SvtBroadcaster; |
| pCell->TakeBroadcaster(pBC); |
| } |
| rLst.StartListening(*pBC); |
| } |
| |
| void ScColumn::MoveListeners( SvtBroadcaster& rSource, SCROW nDestRow ) |
| { |
| SvtBroadcaster* pBC = NULL; |
| ScBaseCell* pCell; |
| |
| SCSIZE nIndex; |
| if (Search(nDestRow,nIndex)) |
| { |
| pCell = pItems[nIndex].pCell; |
| pBC = pCell->GetBroadcaster(); |
| } |
| else |
| { |
| pCell = new ScNoteCell; |
| Insert(nDestRow, pCell); |
| } |
| |
| if (!pBC) |
| { |
| pBC = new SvtBroadcaster; |
| pCell->TakeBroadcaster(pBC); |
| } |
| |
| if (rSource.HasListeners()) |
| { |
| SvtListenerIter aIter( rSource); |
| for (SvtListener* pLst = aIter.GoStart(); pLst; pLst = aIter.GoNext()) |
| { |
| pLst->StartListening( *pBC); |
| pLst->EndListening( rSource); |
| } |
| } |
| } |
| |
| void ScColumn::EndListening( SvtListener& rLst, SCROW nRow ) |
| { |
| SCSIZE nIndex; |
| if (Search(nRow,nIndex)) |
| { |
| ScBaseCell* pCell = pItems[nIndex].pCell; |
| SvtBroadcaster* pBC = pCell->GetBroadcaster(); |
| if (pBC) |
| { |
| rLst.EndListening(*pBC); |
| |
| if (!pBC->HasListeners()) |
| { |
| if (pCell->IsBlank()) |
| DeleteAtIndex(nIndex); |
| else |
| pCell->DeleteBroadcaster(); |
| } |
| } |
| // else |
| // DBG_ERROR("ScColumn::EndListening - kein Broadcaster"); |
| } |
| // else |
| // DBG_ERROR("ScColumn::EndListening - keine Zelle"); |
| } |
| |
| void ScColumn::CompileDBFormula() |
| { |
| if (pItems) |
| for (SCSIZE i = 0; i < nCount; i++) |
| { |
| ScBaseCell* pCell = pItems[i].pCell; |
| if ( pCell->GetCellType() == CELLTYPE_FORMULA ) |
| ((ScFormulaCell*) pCell)->CompileDBFormula(); |
| } |
| } |
| |
| void ScColumn::CompileDBFormula( sal_Bool bCreateFormulaString ) |
| { |
| if (pItems) |
| for (SCSIZE i = 0; i < nCount; i++) |
| { |
| ScBaseCell* pCell = pItems[i].pCell; |
| if ( pCell->GetCellType() == CELLTYPE_FORMULA ) |
| ((ScFormulaCell*) pCell)->CompileDBFormula( bCreateFormulaString ); |
| } |
| } |
| |
| void ScColumn::CompileNameFormula( sal_Bool bCreateFormulaString ) |
| { |
| if (pItems) |
| for (SCSIZE i = 0; i < nCount; i++) |
| { |
| ScBaseCell* pCell = pItems[i].pCell; |
| if ( pCell->GetCellType() == CELLTYPE_FORMULA ) |
| ((ScFormulaCell*) pCell)->CompileNameFormula( bCreateFormulaString ); |
| } |
| } |
| |
| void ScColumn::CompileColRowNameFormula() |
| { |
| if (pItems) |
| for (SCSIZE i = 0; i < nCount; i++) |
| { |
| ScBaseCell* pCell = pItems[i].pCell; |
| if ( pCell->GetCellType() == CELLTYPE_FORMULA ) |
| ((ScFormulaCell*) pCell)->CompileColRowNameFormula(); |
| } |
| } |
| |
| void lcl_UpdateSubTotal( ScFunctionData& rData, ScBaseCell* pCell ) |
| { |
| double nValue = 0.0; |
| sal_Bool bVal = sal_False; |
| sal_Bool bCell = sal_True; |
| switch (pCell->GetCellType()) |
| { |
| case CELLTYPE_VALUE: |
| nValue = ((ScValueCell*)pCell)->GetValue(); |
| bVal = sal_True; |
| break; |
| case CELLTYPE_FORMULA: |
| { |
| if ( rData.eFunc != SUBTOTAL_FUNC_CNT2 ) // da interessiert's nicht |
| { |
| ScFormulaCell* pFC = (ScFormulaCell*)pCell; |
| if ( pFC->GetErrCode() ) |
| { |
| if ( rData.eFunc != SUBTOTAL_FUNC_CNT ) // fuer Anzahl einfach weglassen |
| rData.bError = sal_True; |
| } |
| else if (pFC->IsValue()) |
| { |
| nValue = pFC->GetValue(); |
| bVal = sal_True; |
| } |
| // sonst Text |
| } |
| } |
| break; |
| case CELLTYPE_NOTE: |
| bCell = sal_False; |
| break; |
| // bei Strings nichts |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| |
| if (!rData.bError) |
| { |
| switch (rData.eFunc) |
| { |
| case SUBTOTAL_FUNC_SUM: |
| case SUBTOTAL_FUNC_AVE: |
| if (bVal) |
| { |
| ++rData.nCount; |
| if (!SubTotal::SafePlus( rData.nVal, nValue )) |
| rData.bError = sal_True; |
| } |
| break; |
| case SUBTOTAL_FUNC_CNT: // nur Werte |
| if (bVal) |
| ++rData.nCount; |
| break; |
| case SUBTOTAL_FUNC_CNT2: // alle |
| if (bCell) |
| ++rData.nCount; |
| break; |
| case SUBTOTAL_FUNC_MAX: |
| if (bVal) |
| if (++rData.nCount == 1 || nValue > rData.nVal ) |
| rData.nVal = nValue; |
| break; |
| case SUBTOTAL_FUNC_MIN: |
| if (bVal) |
| if (++rData.nCount == 1 || nValue < rData.nVal ) |
| rData.nVal = nValue; |
| break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| } |
| } |
| |
| // Mehrfachselektion: |
| void ScColumn::UpdateSelectionFunction( const ScMarkData& rMark, |
| ScFunctionData& rData, |
| ScFlatBoolRowSegments& rHiddenRows, |
| sal_Bool bDoExclude, SCROW nExStartRow, SCROW nExEndRow ) |
| { |
| SCSIZE nIndex; |
| ScMarkedDataIter aDataIter(this, &rMark, sal_False); |
| while (aDataIter.Next( nIndex )) |
| { |
| SCROW nRow = pItems[nIndex].nRow; |
| bool bRowHidden = rHiddenRows.getValue(nRow); |
| if ( !bRowHidden ) |
| if ( !bDoExclude || nRow < nExStartRow || nRow > nExEndRow ) |
| lcl_UpdateSubTotal( rData, pItems[nIndex].pCell ); |
| } |
| } |
| |
| // bei bNoMarked die Mehrfachselektion weglassen |
| void ScColumn::UpdateAreaFunction( ScFunctionData& rData, |
| ScFlatBoolRowSegments& rHiddenRows, |
| SCROW nStartRow, SCROW nEndRow ) |
| { |
| SCSIZE nIndex; |
| Search( nStartRow, nIndex ); |
| while ( nIndex<nCount && pItems[nIndex].nRow<=nEndRow ) |
| { |
| SCROW nRow = pItems[nIndex].nRow; |
| bool bRowHidden = rHiddenRows.getValue(nRow); |
| if ( !bRowHidden ) |
| lcl_UpdateSubTotal( rData, pItems[nIndex].pCell ); |
| ++nIndex; |
| } |
| } |
| |
| sal_uLong ScColumn::GetWeightedCount() const |
| { |
| sal_uLong nTotal = 0; |
| |
| // Notizen werden nicht gezaehlt |
| |
| for (SCSIZE i=0; i<nCount; i++) |
| { |
| ScBaseCell* pCell = pItems[i].pCell; |
| switch ( pCell->GetCellType() ) |
| { |
| case CELLTYPE_VALUE: |
| case CELLTYPE_STRING: |
| ++nTotal; |
| break; |
| case CELLTYPE_FORMULA: |
| nTotal += 5 + ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen(); |
| break; |
| case CELLTYPE_EDIT: |
| nTotal += 50; |
| break; |
| default: |
| { |
| // added to avoid warnings |
| } |
| } |
| } |
| |
| return nTotal; |
| } |
| |
| sal_uLong ScColumn::GetCodeCount() const |
| { |
| sal_uLong nCodeCount = 0; |
| |
| for (SCSIZE i=0; i<nCount; i++) |
| { |
| ScBaseCell* pCell = pItems[i].pCell; |
| if ( pCell->GetCellType() == CELLTYPE_FORMULA ) |
| nCodeCount += ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen(); |
| } |
| |
| return nCodeCount; |
| } |
| |
| SCSIZE ScColumn::GetPatternCount() |
| { |
| return this->pAttrArray ? this->pAttrArray->Count() : 0; |
| } |
| |
| SCSIZE ScColumn::GetPatternCount( SCROW nRw1, SCROW nRw2 ) |
| { |
| return this->pAttrArray ? this->pAttrArray->Count( nRw1, nRw2 ) : 0; |
| } |
| |
| bool ScColumn::ReservedPatternCount( SCSIZE nReserved ) |
| { |
| return this->pAttrArray ? this->pAttrArray->Reserve( nReserved ) : false; |
| } |