LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/data - column2.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 461 898 51.3 %
Date: 2012-12-27 Functions: 33 52 63.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "scitems.hxx"
      21             : #include <editeng/eeitem.hxx>
      22             : 
      23             : #include <svx/algitem.hxx>
      24             : #include <editeng/editobj.hxx>
      25             : #include <editeng/editstat.hxx>
      26             : #include <editeng/emphitem.hxx>
      27             : #include <editeng/fhgtitem.hxx>
      28             : #include <editeng/forbiddencharacterstable.hxx>
      29             : #include <svx/rotmodit.hxx>
      30             : #include <editeng/scripttypeitem.hxx>
      31             : #include <editeng/unolingu.hxx>
      32             : #include <editeng/justifyitem.hxx>
      33             : #include <svl/zforlist.hxx>
      34             : #include <svl/broadcast.hxx>
      35             : #include <svl/listeneriter.hxx>
      36             : #include <vcl/outdev.hxx>
      37             : 
      38             : #include "column.hxx"
      39             : #include "cell.hxx"
      40             : #include "document.hxx"
      41             : #include "docpool.hxx"
      42             : #include "attarray.hxx"
      43             : #include "patattr.hxx"
      44             : #include "cellform.hxx"
      45             : #include "stlsheet.hxx"
      46             : #include "rechead.hxx"
      47             : #include "brdcst.hxx"
      48             : #include "editutil.hxx"
      49             : #include "subtotal.hxx"
      50             : #include "markdata.hxx"
      51             : #include "compiler.hxx"         // ScTokenArray GetCodeLen
      52             : #include "dbdata.hxx"
      53             : #include "fillinfo.hxx"
      54             : #include "segmenttree.hxx"
      55             : #include "docparam.hxx"
      56             : 
      57             : #include <math.h>
      58             : 
      59             : // -----------------------------------------------------------------------
      60             : 
      61             : // factor from font size to optimal cell height (text width)
      62             : #define SC_ROT_BREAK_FACTOR     6
      63             : 
      64             : // -----------------------------------------------------------------------
      65             : 
      66          84 : inline bool IsAmbiguousScript( sal_uInt8 nScript )
      67             : {
      68             :     //! move to a header file
      69             :     return ( nScript != SCRIPTTYPE_LATIN &&
      70             :              nScript != SCRIPTTYPE_ASIAN &&
      71          84 :              nScript != SCRIPTTYPE_COMPLEX );
      72             : }
      73             : 
      74             : // -----------------------------------------------------------------------------------------
      75             : 
      76             : //
      77             : //  Datei-Operationen
      78             : //
      79             : 
      80             : // -----------------------------------------------------------------------------------------
      81             : 
      82             : 
      83         102 : long ScColumn::GetNeededSize(
      84             :     SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY,
      85             :     const Fraction& rZoomX, const Fraction& rZoomY,
      86             :     bool bWidth, const ScNeededSizeOptions& rOptions ) const
      87             : {
      88         102 :     long nValue=0;
      89             :     SCSIZE nIndex;
      90         102 :     double nPPT = bWidth ? nPPTX : nPPTY;
      91         102 :     if (Search(nRow,nIndex))
      92             :     {
      93         102 :         ScBaseCell* pCell = maItems[nIndex].pCell;
      94         102 :         const ScPatternAttr* pPattern = rOptions.pPattern;
      95         102 :         if (!pPattern)
      96          78 :             pPattern = pAttrArray->GetPattern( nRow );
      97             : 
      98             :         //      zusammengefasst?
      99             :         //      Merge nicht in bedingter Formatierung
     100             : 
     101         102 :         const ScMergeAttr*      pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
     102         102 :         const ScMergeFlagAttr*  pFlag = (const ScMergeFlagAttr*)&pPattern->GetItem(ATTR_MERGE_FLAG);
     103             : 
     104         102 :         if ( bWidth )
     105             :         {
     106          86 :             if ( pFlag->IsHorOverlapped() )
     107           0 :                 return 0;
     108          86 :             if ( rOptions.bSkipMerged && pMerge->GetColMerge() > 1 )
     109           0 :                 return 0;
     110             :         }
     111             :         else
     112             :         {
     113          16 :             if ( pFlag->IsVerOverlapped() )
     114           0 :                 return 0;
     115          16 :             if ( rOptions.bSkipMerged && pMerge->GetRowMerge() > 1 )
     116           0 :                 return 0;
     117             :         }
     118             : 
     119             :         //      bedingte Formatierung
     120         102 :         const SfxItemSet* pCondSet = pDocument->GetCondResult( nCol, nRow, nTab );
     121             : 
     122             :         //  Zeilenumbruch?
     123             : 
     124             :         const SfxPoolItem* pCondItem;
     125             :         SvxCellHorJustify eHorJust;
     126         102 :         if (pCondSet &&
     127           0 :                 pCondSet->GetItemState(ATTR_HOR_JUSTIFY, true, &pCondItem) == SFX_ITEM_SET)
     128           0 :             eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem*)pCondItem)->GetValue();
     129             :         else
     130             :             eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
     131         102 :                                             pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue();
     132             :         bool bBreak;
     133         102 :         if ( eHorJust == SVX_HOR_JUSTIFY_BLOCK )
     134           1 :             bBreak = true;
     135         101 :         else if ( pCondSet &&
     136           0 :                     pCondSet->GetItemState(ATTR_LINEBREAK, true, &pCondItem) == SFX_ITEM_SET)
     137           0 :             bBreak = ((const SfxBoolItem*)pCondItem)->GetValue();
     138             :         else
     139         101 :             bBreak = ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue();
     140             : 
     141         102 :         SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
     142         102 :         sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet );
     143             :         // #i111387# disable automatic line breaks only for "General" number format
     144         102 :         if ( bBreak && pCell->HasValueData() && ( nFormat % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 )
     145             :         {
     146             :             // also take formula result type into account for number format
     147           0 :             if ( pCell->GetCellType() != CELLTYPE_FORMULA ||
     148           0 :                  ( static_cast<ScFormulaCell*>(pCell)->GetStandardFormat(*pFormatter, nFormat) % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 )
     149           0 :                 bBreak = false;
     150             :         }
     151             : 
     152             :         //  get other attributes from pattern and conditional formatting
     153             : 
     154         102 :         SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet );
     155             :         bool bAsianVertical = ( eOrient == SVX_ORIENTATION_STACKED &&
     156         102 :                 ((const SfxBoolItem&)pPattern->GetItem( ATTR_VERTICAL_ASIAN, pCondSet )).GetValue() );
     157         102 :         if ( bAsianVertical )
     158           0 :             bBreak = false;
     159             : 
     160         102 :         if ( bWidth && bBreak )     // after determining bAsianVertical (bBreak may be reset)
     161           2 :             return 0;
     162             : 
     163         100 :         long nRotate = 0;
     164         100 :         SvxRotateMode eRotMode = SVX_ROTATE_MODE_STANDARD;
     165         100 :         if ( eOrient == SVX_ORIENTATION_STANDARD )
     166             :         {
     167         100 :             if (pCondSet &&
     168           0 :                     pCondSet->GetItemState(ATTR_ROTATE_VALUE, true, &pCondItem) == SFX_ITEM_SET)
     169           0 :                 nRotate = ((const SfxInt32Item*)pCondItem)->GetValue();
     170             :             else
     171         100 :                 nRotate = ((const SfxInt32Item&)pPattern->GetItem(ATTR_ROTATE_VALUE)).GetValue();
     172         100 :             if ( nRotate )
     173             :             {
     174           0 :                 if (pCondSet &&
     175           0 :                         pCondSet->GetItemState(ATTR_ROTATE_MODE, true, &pCondItem) == SFX_ITEM_SET)
     176           0 :                     eRotMode = (SvxRotateMode)((const SvxRotateModeItem*)pCondItem)->GetValue();
     177             :                 else
     178             :                     eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
     179           0 :                                                 pPattern->GetItem(ATTR_ROTATE_MODE)).GetValue();
     180             : 
     181           0 :                 if ( nRotate == 18000 )
     182           0 :                     eRotMode = SVX_ROTATE_MODE_STANDARD;    // keinen Ueberlauf
     183             :             }
     184             :         }
     185             : 
     186         100 :         if ( eHorJust == SVX_HOR_JUSTIFY_REPEAT )
     187             :         {
     188             :             // ignore orientation/rotation if "repeat" is active
     189           0 :             eOrient = SVX_ORIENTATION_STANDARD;
     190           0 :             nRotate = 0;
     191           0 :             bAsianVertical = false;
     192             :         }
     193             : 
     194             :         const SvxMarginItem* pMargin;
     195         100 :         if (pCondSet &&
     196           0 :                 pCondSet->GetItemState(ATTR_MARGIN, true, &pCondItem) == SFX_ITEM_SET)
     197           0 :             pMargin = (const SvxMarginItem*) pCondItem;
     198             :         else
     199         100 :             pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN);
     200         100 :         sal_uInt16 nIndent = 0;
     201         100 :         if ( eHorJust == SVX_HOR_JUSTIFY_LEFT )
     202             :         {
     203           2 :             if (pCondSet &&
     204           0 :                     pCondSet->GetItemState(ATTR_INDENT, true, &pCondItem) == SFX_ITEM_SET)
     205           0 :                 nIndent = ((const SfxUInt16Item*)pCondItem)->GetValue();
     206             :             else
     207           2 :                 nIndent = ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue();
     208             :         }
     209             : 
     210         100 :         sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, pCell );
     211         100 :         if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType();
     212             : 
     213             :         //  also call SetFont for edit cells, because bGetFont may be set only once
     214             :         //  bGetFont is set also if script type changes
     215         100 :         if (rOptions.bGetFont)
     216             :         {
     217         100 :             Fraction aFontZoom = ( eOrient == SVX_ORIENTATION_STANDARD ) ? rZoomX : rZoomY;
     218         100 :             Font aFont;
     219             :             // font color doesn't matter here
     220         100 :             pPattern->GetFont( aFont, SC_AUTOCOL_BLACK, pDev, &aFontZoom, pCondSet, nScript );
     221         100 :             pDev->SetFont(aFont);
     222             :         }
     223             : 
     224         100 :         bool bAddMargin = true;
     225         100 :         CellType eCellType = pCell->GetCellType();
     226             : 
     227             :         bool bEditEngine = ( eCellType == CELLTYPE_EDIT ||
     228             :                                 eOrient == SVX_ORIENTATION_STACKED ||
     229          83 :                                 IsAmbiguousScript( nScript ) ||
     230         183 :                                 ((eCellType == CELLTYPE_FORMULA) && ((ScFormulaCell*)pCell)->IsMultilineResult()) );
     231             : 
     232         100 :         if (!bEditEngine)                                   // direkte Ausgabe
     233             :         {
     234             :             Color* pColor;
     235          83 :             rtl::OUString aValStr;
     236             :             ScCellFormat::GetString( pCell, nFormat, aValStr, &pColor,
     237             :                                         *pFormatter,
     238          83 :                                         true, rOptions.bFormula, ftCheck );
     239          83 :             if (!aValStr.isEmpty())
     240             :             {
     241             :                 //  SetFont ist nach oben verschoben
     242             : 
     243          83 :                 Size aSize( pDev->GetTextWidth( aValStr ), pDev->GetTextHeight() );
     244          83 :                 if ( eOrient != SVX_ORIENTATION_STANDARD )
     245             :                 {
     246           0 :                     long nTemp = aSize.Width();
     247           0 :                     aSize.Width() = aSize.Height();
     248           0 :                     aSize.Height() = nTemp;
     249             :                 }
     250          83 :                 else if ( nRotate )
     251             :                 {
     252             :                     //! unterschiedliche Skalierung X/Y beruecksichtigen
     253             : 
     254           0 :                     double nRealOrient = nRotate * F_PI18000;   // nRotate sind 1/100 Grad
     255           0 :                     double nCosAbs = fabs( cos( nRealOrient ) );
     256           0 :                     double nSinAbs = fabs( sin( nRealOrient ) );
     257           0 :                     long nHeight = (long)( aSize.Height() * nCosAbs + aSize.Width() * nSinAbs );
     258             :                     long nWidth;
     259           0 :                     if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
     260           0 :                         nWidth  = (long)( aSize.Width() * nCosAbs + aSize.Height() * nSinAbs );
     261           0 :                     else if ( rOptions.bTotalSize )
     262             :                     {
     263           0 :                         nWidth = (long) ( pDocument->GetColWidth( nCol,nTab ) * nPPT );
     264           0 :                         bAddMargin = false;
     265             :                         //  nur nach rechts:
     266             :                         //! unterscheiden nach Ausrichtung oben/unten (nur Text/ganze Hoehe)
     267           0 :                         if ( pPattern->GetRotateDir( pCondSet ) == SC_ROTDIR_RIGHT )
     268           0 :                             nWidth += (long)( pDocument->GetRowHeight( nRow,nTab ) *
     269           0 :                                                 nPPT * nCosAbs / nSinAbs );
     270             :                     }
     271             :                     else
     272           0 :                         nWidth  = (long)( aSize.Height() / nSinAbs );   //! begrenzen?
     273             : 
     274           0 :                     if ( bBreak && !rOptions.bTotalSize )
     275             :                     {
     276             :                         //  limit size for line break
     277           0 :                         long nCmp = pDev->GetFont().GetSize().Height() * SC_ROT_BREAK_FACTOR;
     278           0 :                         if ( nHeight > nCmp )
     279           0 :                             nHeight = nCmp;
     280             :                     }
     281             : 
     282           0 :                     aSize = Size( nWidth, nHeight );
     283             :                 }
     284          83 :                 nValue = bWidth ? aSize.Width() : aSize.Height();
     285             : 
     286          83 :                 if ( bAddMargin )
     287             :                 {
     288          83 :                     if (bWidth)
     289             :                     {
     290          83 :                         nValue += (long) ( pMargin->GetLeftMargin() * nPPT ) +
     291          83 :                                   (long) ( pMargin->GetRightMargin() * nPPT );
     292          83 :                         if ( nIndent )
     293           0 :                             nValue += (long) ( nIndent * nPPT );
     294             :                     }
     295             :                     else
     296           0 :                         nValue += (long) ( pMargin->GetTopMargin() * nPPT ) +
     297           0 :                                   (long) ( pMargin->GetBottomMargin() * nPPT );
     298             :                 }
     299             : 
     300             :                                                 //  Zeilenumbruch ausgefuehrt ?
     301             : 
     302          83 :                 if ( bBreak && !bWidth )
     303             :                 {
     304             :                     //  Test mit EditEngine zur Sicherheit schon bei 90%
     305             :                     //  (wegen Rundungsfehlern und weil EditEngine teilweise anders formatiert)
     306             : 
     307           0 :                     long nDocPixel = (long) ( ( pDocument->GetColWidth( nCol,nTab ) -
     308           0 :                                         pMargin->GetLeftMargin() - pMargin->GetRightMargin() -
     309             :                                         nIndent )
     310           0 :                                         * nPPT );
     311           0 :                     nDocPixel = (nDocPixel * 9) / 10;           // zur Sicherheit
     312           0 :                     if ( aSize.Width() > nDocPixel )
     313           0 :                         bEditEngine = true;
     314             :                 }
     315          83 :             }
     316             :         }
     317             : 
     318         100 :         if (bEditEngine)
     319             :         {
     320             :             //  der Font wird bei !bEditEngine nicht jedesmal neu gesetzt
     321          17 :             Font aOldFont = pDev->GetFont();
     322             : 
     323          17 :             MapMode aHMMMode( MAP_100TH_MM, Point(), rZoomX, rZoomY );
     324             : 
     325             :             // am Dokument speichern ?
     326          17 :             ScFieldEditEngine* pEngine = pDocument->CreateFieldEditEngine();
     327             : 
     328          17 :             pEngine->SetUpdateMode( false );
     329          17 :             bool bTextWysiwyg = ( pDev->GetOutDevType() == OUTDEV_PRINTER );
     330          17 :             sal_uLong nCtrl = pEngine->GetControlWord();
     331          17 :             if ( bTextWysiwyg )
     332           1 :                 nCtrl |= EE_CNTRL_FORMAT100;
     333             :             else
     334          16 :                 nCtrl &= ~EE_CNTRL_FORMAT100;
     335          17 :             pEngine->SetControlWord( nCtrl );
     336          17 :             MapMode aOld = pDev->GetMapMode();
     337          17 :             pDev->SetMapMode( aHMMMode );
     338          17 :             pEngine->SetRefDevice( pDev );
     339          17 :             pDocument->ApplyAsianEditSettings( *pEngine );
     340          17 :             SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() );
     341          17 :             pPattern->FillEditItemSet( pSet, pCondSet );
     342             : 
     343             : //          no longer needed, are setted with the text (is faster)
     344             : //          pEngine->SetDefaults( pSet );
     345             : 
     346          17 :             if ( ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() ) {
     347             : 
     348           0 :                 com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
     349           0 :                 pEngine->SetHyphenator( xXHyphenator );
     350             :             }
     351             : 
     352          17 :             Size aPaper = Size( 1000000, 1000000 );
     353          17 :             if ( eOrient==SVX_ORIENTATION_STACKED && !bAsianVertical )
     354           0 :                 aPaper.Width() = 1;
     355          17 :             else if (bBreak)
     356             :             {
     357           0 :                 double fWidthFactor = nPPTX;
     358           0 :                 if ( bTextWysiwyg )
     359             :                 {
     360             :                     //  if text is formatted for printer, don't use PixelToLogic,
     361             :                     //  to ensure the exact same paper width (and same line breaks) as in
     362             :                     //  ScEditUtil::GetEditArea, used for output.
     363             : 
     364           0 :                     fWidthFactor = HMM_PER_TWIPS;
     365             :                 }
     366             : 
     367             :                 // use original width for hidden columns:
     368           0 :                 long nDocWidth = (long) ( pDocument->GetOriginalWidth(nCol,nTab) * fWidthFactor );
     369           0 :                 SCCOL nColMerge = pMerge->GetColMerge();
     370           0 :                 if (nColMerge > 1)
     371           0 :                     for (SCCOL nColAdd=1; nColAdd<nColMerge; nColAdd++)
     372           0 :                         nDocWidth += (long) ( pDocument->GetColWidth(nCol+nColAdd,nTab) * fWidthFactor );
     373           0 :                 nDocWidth -= (long) ( pMargin->GetLeftMargin() * fWidthFactor )
     374           0 :                            + (long) ( pMargin->GetRightMargin() * fWidthFactor )
     375           0 :                            + 1;     // Ausgabebereich ist Breite-1 Pixel (wegen Gitterlinien)
     376           0 :                 if ( nIndent )
     377           0 :                     nDocWidth -= (long) ( nIndent * fWidthFactor );
     378             : 
     379             :                 // space for AutoFilter button:  20 * nZoom/100
     380           0 :                 if ( pFlag->HasAutoFilter() && !bTextWysiwyg )
     381           0 :                     nDocWidth -= (rZoomX.GetNumerator()*20)/rZoomX.GetDenominator();
     382             : 
     383           0 :                 aPaper.Width() = nDocWidth;
     384             : 
     385           0 :                 if ( !bTextWysiwyg )
     386           0 :                     aPaper = pDev->PixelToLogic( aPaper, aHMMMode );
     387             :             }
     388          17 :             pEngine->SetPaperSize(aPaper);
     389             : 
     390          17 :             if ( pCell->GetCellType() == CELLTYPE_EDIT )
     391             :             {
     392             :                 const EditTextObject* pData;
     393          17 :                 ((ScEditCell*)pCell)->GetData(pData);
     394          17 :                 pEngine->SetTextNewDefaults(*pData, pSet);
     395             :             }
     396             :             else
     397             :             {
     398             :                 Color* pColor;
     399           0 :                 rtl::OUString aString;
     400             :                 ScCellFormat::GetString( pCell, nFormat, aString, &pColor,
     401             :                                             *pFormatter,
     402           0 :                                             true, rOptions.bFormula, ftCheck );
     403           0 :                 if (!aString.isEmpty())
     404           0 :                     pEngine->SetTextNewDefaults(aString, pSet);
     405             :                 else
     406           0 :                     pEngine->SetDefaults(pSet);
     407             :             }
     408             : 
     409          17 :             bool bEngineVertical = pEngine->IsVertical();
     410          17 :             pEngine->SetVertical( bAsianVertical );
     411          17 :             pEngine->SetUpdateMode( true );
     412             : 
     413          17 :             bool bEdWidth = bWidth;
     414          17 :             if ( eOrient != SVX_ORIENTATION_STANDARD && eOrient != SVX_ORIENTATION_STACKED )
     415           0 :                 bEdWidth = !bEdWidth;
     416          17 :             if ( nRotate )
     417             :             {
     418             :                 //! unterschiedliche Skalierung X/Y beruecksichtigen
     419             : 
     420           0 :                 Size aSize( pEngine->CalcTextWidth(), pEngine->GetTextHeight() );
     421           0 :                 double nRealOrient = nRotate * F_PI18000;   // nRotate sind 1/100 Grad
     422           0 :                 double nCosAbs = fabs( cos( nRealOrient ) );
     423           0 :                 double nSinAbs = fabs( sin( nRealOrient ) );
     424           0 :                 long nHeight = (long)( aSize.Height() * nCosAbs + aSize.Width() * nSinAbs );
     425             :                 long nWidth;
     426           0 :                 if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
     427           0 :                     nWidth  = (long)( aSize.Width() * nCosAbs + aSize.Height() * nSinAbs );
     428           0 :                 else if ( rOptions.bTotalSize )
     429             :                 {
     430           0 :                     nWidth = (long) ( pDocument->GetColWidth( nCol,nTab ) * nPPT );
     431           0 :                     bAddMargin = false;
     432           0 :                     if ( pPattern->GetRotateDir( pCondSet ) == SC_ROTDIR_RIGHT )
     433           0 :                         nWidth += (long)( pDocument->GetRowHeight( nRow,nTab ) *
     434           0 :                                             nPPT * nCosAbs / nSinAbs );
     435             :                 }
     436             :                 else
     437           0 :                     nWidth  = (long)( aSize.Height() / nSinAbs );   //! begrenzen?
     438           0 :                 aSize = Size( nWidth, nHeight );
     439             : 
     440           0 :                 Size aPixSize = pDev->LogicToPixel( aSize, aHMMMode );
     441           0 :                 if ( bEdWidth )
     442           0 :                     nValue = aPixSize.Width();
     443             :                 else
     444             :                 {
     445           0 :                     nValue = aPixSize.Height();
     446             : 
     447           0 :                     if ( bBreak && !rOptions.bTotalSize )
     448             :                     {
     449             :                         //  limit size for line break
     450           0 :                         long nCmp = aOldFont.GetSize().Height() * SC_ROT_BREAK_FACTOR;
     451           0 :                         if ( nValue > nCmp )
     452           0 :                             nValue = nCmp;
     453             :                     }
     454             :                 }
     455             :             }
     456          17 :             else if ( bEdWidth )
     457             :             {
     458           1 :                 if (bBreak)
     459           0 :                     nValue = 0;
     460             :                 else
     461           1 :                     nValue = pDev->LogicToPixel(Size( pEngine->CalcTextWidth(), 0 ),
     462           1 :                                         aHMMMode).Width();
     463             :             }
     464             :             else            // Hoehe
     465             :             {
     466          16 :                 nValue = pDev->LogicToPixel(Size( 0, pEngine->GetTextHeight() ),
     467          16 :                                     aHMMMode).Height();
     468             : 
     469             :                 // With non-100% zoom and several lines or paragraphs, don't shrink below the result with FORMAT100 set
     470          16 :                 if ( !bTextWysiwyg && ( rZoomY.GetNumerator() != 1 || rZoomY.GetDenominator() != 1 ) &&
     471           0 :                      ( pEngine->GetParagraphCount() > 1 || ( bBreak && pEngine->GetLineCount(0) > 1 ) ) )
     472             :                 {
     473           0 :                     pEngine->SetControlWord( nCtrl | EE_CNTRL_FORMAT100 );
     474           0 :                     pEngine->QuickFormatDoc( sal_True );
     475           0 :                     long nSecondValue = pDev->LogicToPixel(Size( 0, pEngine->GetTextHeight() ), aHMMMode).Height();
     476           0 :                     if ( nSecondValue > nValue )
     477           0 :                         nValue = nSecondValue;
     478             :                 }
     479             :             }
     480             : 
     481          17 :             if ( nValue && bAddMargin )
     482             :             {
     483          17 :                 if (bWidth)
     484             :                 {
     485           1 :                     nValue += (long) ( pMargin->GetLeftMargin() * nPPT ) +
     486           1 :                               (long) ( pMargin->GetRightMargin() * nPPT );
     487           1 :                     if (nIndent)
     488           0 :                         nValue += (long) ( nIndent * nPPT );
     489             :                 }
     490             :                 else
     491             :                 {
     492          16 :                     nValue += (long) ( pMargin->GetTopMargin() * nPPT ) +
     493          16 :                               (long) ( pMargin->GetBottomMargin() * nPPT );
     494             : 
     495          16 :                     if ( bAsianVertical && pDev->GetOutDevType() != OUTDEV_PRINTER )
     496             :                     {
     497             :                         //  add 1pt extra (default margin value) for line breaks with SetVertical
     498           0 :                         nValue += (long) ( 20 * nPPT );
     499             :                     }
     500             :                 }
     501             :             }
     502             : 
     503             :             //  EditEngine is cached and re-used, so the old vertical flag must be restored
     504          17 :             pEngine->SetVertical( bEngineVertical );
     505             : 
     506          17 :             pDocument->DisposeFieldEditEngine(pEngine);
     507             : 
     508          17 :             pDev->SetMapMode( aOld );
     509          17 :             pDev->SetFont( aOldFont );
     510             :         }
     511             : 
     512         100 :         if (bWidth)
     513             :         {
     514             :             //      Platz fuer Autofilter-Button
     515             :             //      20 * nZoom/100
     516             :             //      bedingte Formatierung hier nicht interessant
     517             : 
     518          84 :             sal_Int16 nFlags = ((const ScMergeFlagAttr&)pPattern->GetItem(ATTR_MERGE_FLAG)).GetValue();
     519          84 :             if (nFlags & SC_MF_AUTO)
     520           4 :                 nValue += (rZoomX.GetNumerator()*20)/rZoomX.GetDenominator();
     521             :         }
     522             :     }
     523         100 :     return nValue;
     524             : }
     525             : 
     526             : 
     527          78 : sal_uInt16 ScColumn::GetOptimalColWidth(
     528             :     OutputDevice* pDev, double nPPTX, double nPPTY, const Fraction& rZoomX, const Fraction& rZoomY,
     529             :     bool bFormula, sal_uInt16 nOldWidth, const ScMarkData* pMarkData, const ScColWidthParam* pParam) const
     530             : {
     531          78 :     if ( maItems.empty() )
     532          11 :         return nOldWidth;
     533             : 
     534          67 :     sal_uInt16  nWidth = (sal_uInt16) (nOldWidth * nPPTX);
     535          67 :     bool    bFound = false;
     536             : 
     537             :     SCSIZE nIndex;
     538          67 :     ScMarkedDataIter aDataIter(this, pMarkData, true);
     539          67 :     if ( pParam && pParam->mbSimpleText )
     540             :     {   // alles eins bis auf NumberFormate
     541          64 :         const ScPatternAttr* pPattern = GetPattern( 0 );
     542          64 :         Font aFont;
     543             :         // font color doesn't matter here
     544          64 :         pPattern->GetFont( aFont, SC_AUTOCOL_BLACK, pDev, &rZoomX, NULL );
     545          64 :         pDev->SetFont( aFont );
     546          64 :         const SvxMarginItem* pMargin = (const SvxMarginItem*) &pPattern->GetItem(ATTR_MARGIN);
     547          64 :         long nMargin = (long) ( pMargin->GetLeftMargin() * nPPTX ) +
     548          64 :                         (long) ( pMargin->GetRightMargin() * nPPTX );
     549             : 
     550             :         // Try to find the row that has the longest string, and measure the width of that string.
     551          64 :         SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
     552          64 :         sal_uInt32 nFormat = pPattern->GetNumberFormat( pFormatter );
     553          64 :         rtl::OUString aLongStr;
     554             :         Color* pColor;
     555          64 :         if (pParam->mnMaxTextRow >= 0)
     556             :         {
     557           0 :             ScBaseCell* pCell = GetCell(pParam->mnMaxTextRow);
     558             :             ScCellFormat::GetString(
     559           0 :                 pCell, nFormat, aLongStr, &pColor, *pFormatter, true, false, ftCheck );
     560             :         }
     561             :         else
     562             :         {
     563          64 :             xub_StrLen nLongLen = 0;
     564        2725 :             while (aDataIter.Next(nIndex))
     565             :             {
     566        2597 :                 if (nIndex >= maItems.size())
     567             :                     // Out-of-bound reached.  No need to keep going.
     568             :                     break;
     569             : 
     570        2597 :                 ScBaseCell* pCell = maItems[nIndex].pCell;
     571        2597 :                 rtl::OUString aValStr;
     572             :                 ScCellFormat::GetString(
     573        2597 :                     pCell, nFormat, aValStr, &pColor, *pFormatter, true, false, ftCheck );
     574             : 
     575        2597 :                 if (aValStr.getLength() > nLongLen)
     576             :                 {
     577         119 :                     nLongLen = aValStr.getLength();
     578         119 :                     aLongStr = aValStr;
     579             :                 }
     580        2597 :             }
     581             :         }
     582             : 
     583          64 :         if (!aLongStr.isEmpty())
     584             :         {
     585          64 :             nWidth = pDev->GetTextWidth(aLongStr) + static_cast<sal_uInt16>(nMargin);
     586          64 :             bFound = true;
     587          64 :         }
     588             :     }
     589             :     else
     590             :     {
     591           3 :         ScNeededSizeOptions aOptions;
     592           3 :         aOptions.bFormula = bFormula;
     593           3 :         const ScPatternAttr* pOldPattern = NULL;
     594           3 :         sal_uInt8 nOldScript = 0;
     595             : 
     596          14 :         while (aDataIter.Next( nIndex ))
     597             :         {
     598           8 :             SCROW nRow = maItems[nIndex].nRow;
     599             : 
     600           8 :             sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, maItems[nIndex].pCell );
     601           8 :             if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType();
     602             : 
     603           8 :             const ScPatternAttr* pPattern = GetPattern( nRow );
     604           8 :             aOptions.pPattern = pPattern;
     605           8 :             aOptions.bGetFont = (pPattern != pOldPattern || nScript != nOldScript);
     606             :             sal_uInt16 nThis = (sal_uInt16) GetNeededSize( nRow, pDev, nPPTX, nPPTY,
     607           8 :                 rZoomX, rZoomY, true, aOptions );
     608           8 :             pOldPattern = pPattern;
     609           8 :             if (nThis)
     610             :             {
     611           8 :                 if (nThis>nWidth || !bFound)
     612             :                 {
     613           5 :                     nWidth = nThis;
     614           5 :                     bFound = true;
     615             :                 }
     616             :             }
     617             :         }
     618             :     }
     619             : 
     620          67 :     if (bFound)
     621             :     {
     622          67 :         nWidth += 2;
     623          67 :         sal_uInt16 nTwips = (sal_uInt16) (nWidth / nPPTX);
     624          67 :         return nTwips;
     625             :     }
     626             :     else
     627           0 :         return nOldWidth;
     628             : }
     629             : 
     630      263366 : static sal_uInt16 lcl_GetAttribHeight( const ScPatternAttr& rPattern, sal_uInt16 nFontHeightId )
     631             : {
     632      263366 :     sal_uInt16 nHeight = (sal_uInt16) ((const SvxFontHeightItem&) rPattern.GetItem(nFontHeightId)).GetHeight();
     633      263366 :     const SvxMarginItem* pMargin = (const SvxMarginItem*) &rPattern.GetItem(ATTR_MARGIN);
     634      263366 :     nHeight += nHeight / 5;
     635             :     //  gibt bei 10pt 240
     636             : 
     637      263366 :     if ( ((const SvxEmphasisMarkItem&)rPattern.
     638      263366 :             GetItem(ATTR_FONT_EMPHASISMARK)).GetEmphasisMark() != EMPHASISMARK_NONE )
     639             :     {
     640             :         //  add height for emphasis marks
     641             :         //! font metrics should be used instead
     642           0 :         nHeight += nHeight / 4;
     643             :     }
     644             : 
     645      263366 :     if ( nHeight + 240 > ScGlobal::nDefFontHeight )
     646             :     {
     647      263366 :         nHeight = sal::static_int_cast<sal_uInt16>( nHeight + ScGlobal::nDefFontHeight );
     648      263366 :         nHeight -= 240;
     649             :     }
     650             : 
     651             :     //  Standard-Hoehe: TextHeight + Raender - 23
     652             :     //  -> 257 unter Windows
     653             : 
     654      263366 :     if (nHeight > STD_ROWHEIGHT_DIFF)
     655      263366 :         nHeight -= STD_ROWHEIGHT_DIFF;
     656             : 
     657      263366 :     nHeight += pMargin->GetTopMargin() + pMargin->GetBottomMargin();
     658             : 
     659      263366 :     return nHeight;
     660             : }
     661             : 
     662             : //  pHeight in Twips
     663             : //  nMinHeight, nMinStart zur Optimierung: ab nRow >= nMinStart ist mindestens nMinHeight
     664             : //  (wird nur bei bStdAllowed ausgewertet)
     665             : 
     666      263168 : void ScColumn::GetOptimalHeight(
     667             :     SCROW nStartRow, SCROW nEndRow, sal_uInt16* pHeight, OutputDevice* pDev,
     668             :     double nPPTX, double nPPTY, const Fraction& rZoomX, const Fraction& rZoomY,
     669             :     bool bShrink, sal_uInt16 nMinHeight, SCROW nMinStart) const
     670             : {
     671      263168 :     ScAttrIterator aIter( pAttrArray, nStartRow, nEndRow );
     672             : 
     673      263168 :     SCROW nStart = -1;
     674      263168 :     SCROW nEnd = -1;
     675      263168 :     SCROW nEditPos = 0;
     676      263168 :     SCROW nNextEnd = 0;
     677             : 
     678             :     //  bei bedingter Formatierung werden immer die einzelnen Zellen angesehen
     679             : 
     680      263168 :     const ScPatternAttr* pPattern = aIter.Next(nStart,nEnd);
     681      789727 :     while ( pPattern )
     682             :     {
     683      263391 :         const ScMergeAttr*      pMerge = (const ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
     684      263391 :         const ScMergeFlagAttr*  pFlag = (const ScMergeFlagAttr*)&pPattern->GetItem(ATTR_MERGE_FLAG);
     685      263391 :         if ( pMerge->GetRowMerge() > 1 || pFlag->IsOverlapped() )
     686             :         {
     687             :             //  nix - vertikal bei der zusammengefassten und den ueberdeckten,
     688             :             //        horizontal nur bei den ueberdeckten (unsichtbaren) -
     689             :             //        eine nur horizontal zusammengefasste wird aber beruecksichtigt
     690             :         }
     691             :         else
     692             :         {
     693      263382 :             SCROW nRow = 0;
     694      263382 :             bool bStdAllowed = (pPattern->GetCellOrientation() == SVX_ORIENTATION_STANDARD);
     695      263382 :             bool bStdOnly = false;
     696      263382 :             if (bStdAllowed)
     697             :             {
     698      263382 :                 bool bBreak = ((SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue() ||
     699             :                                 ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
     700      263382 :                                     GetItem( ATTR_HOR_JUSTIFY )).GetValue() ==
     701      526764 :                                     SVX_HOR_JUSTIFY_BLOCK);
     702      263382 :                 bStdOnly = !bBreak;
     703             : 
     704             :                 // bedingte Formatierung: Zellen durchgehen
     705      526764 :                 if (bStdOnly &&
     706             :                     !static_cast<const ScCondFormatItem&>(pPattern->GetItem(
     707      263382 :                             ATTR_CONDITIONAL)).GetCondFormatData().empty())
     708             :                 {
     709           0 :                     bStdOnly = false;
     710             :                 }
     711             : 
     712             :                 // gedrehter Text: Zellen durchgehen
     713      526764 :                 if ( bStdOnly && ((const SfxInt32Item&)pPattern->
     714      263382 :                                     GetItem(ATTR_ROTATE_VALUE)).GetValue() )
     715           0 :                     bStdOnly = false;
     716             :             }
     717             : 
     718      263382 :             if (bStdOnly)
     719      263382 :                 if (HasEditCells(nStart,nEnd,nEditPos))     // includes mixed script types
     720             :                 {
     721          31 :                     if (nEditPos == nStart)
     722             :                     {
     723          16 :                         bStdOnly = false;
     724          16 :                         if (nEnd > nEditPos)
     725          15 :                             nNextEnd = nEnd;
     726          16 :                         nEnd = nEditPos;                // einzeln ausrechnen
     727          16 :                         bStdAllowed = false;            // wird auf jeden Fall per Zelle berechnet
     728             :                     }
     729             :                     else
     730             :                     {
     731          15 :                         nNextEnd = nEnd;
     732          15 :                         nEnd = nEditPos - 1;            // Standard - Teil
     733             :                     }
     734             :                 }
     735             : 
     736      263382 :             if (bStdAllowed)
     737             :             {
     738      263366 :                 sal_uInt16 nLatHeight = 0;
     739      263366 :                 sal_uInt16 nCjkHeight = 0;
     740      263366 :                 sal_uInt16 nCtlHeight = 0;
     741             :                 sal_uInt16 nDefHeight;
     742      263366 :                 sal_uInt8 nDefScript = ScGlobal::GetDefaultScriptType();
     743      263366 :                 if ( nDefScript == SCRIPTTYPE_ASIAN )
     744           0 :                     nDefHeight = nCjkHeight = lcl_GetAttribHeight( *pPattern, ATTR_CJK_FONT_HEIGHT );
     745      263366 :                 else if ( nDefScript == SCRIPTTYPE_COMPLEX )
     746           0 :                     nDefHeight = nCtlHeight = lcl_GetAttribHeight( *pPattern, ATTR_CTL_FONT_HEIGHT );
     747             :                 else
     748      263366 :                     nDefHeight = nLatHeight = lcl_GetAttribHeight( *pPattern, ATTR_FONT_HEIGHT );
     749             : 
     750             :                 //  if everything below is already larger, the loop doesn't have to
     751             :                 //  be run again
     752      263366 :                 SCROW nStdEnd = nEnd;
     753      263366 :                 if ( nDefHeight <= nMinHeight && nStdEnd >= nMinStart )
     754      263109 :                     nStdEnd = (nMinStart>0) ? nMinStart-1 : 0;
     755             : 
     756   258472201 :                 for (nRow=nStart; nRow<=nStdEnd; nRow++)
     757   258208835 :                     if (nDefHeight > pHeight[nRow-nStartRow])
     758   257950016 :                         pHeight[nRow-nStartRow] = nDefHeight;
     759             : 
     760      263366 :                 if ( bStdOnly )
     761             :                 {
     762             :                     //  if cells are not handled individually below,
     763             :                     //  check for cells with different script type
     764             : 
     765             :                     SCSIZE nIndex;
     766      263366 :                     Search(nStart,nIndex);
     767      531640 :                     while ( nIndex < maItems.size() && (nRow=maItems[nIndex].nRow) <= nEnd )
     768             :                     {
     769        4908 :                         sal_uInt8 nScript = pDocument->GetScriptType( nCol, nRow, nTab, maItems[nIndex].pCell );
     770        4908 :                         if ( nScript != nDefScript )
     771             :                         {
     772          57 :                             if ( nScript == SCRIPTTYPE_ASIAN )
     773             :                             {
     774           0 :                                 if ( nCjkHeight == 0 )
     775           0 :                                     nCjkHeight = lcl_GetAttribHeight( *pPattern, ATTR_CJK_FONT_HEIGHT );
     776           0 :                                 if (nCjkHeight > pHeight[nRow-nStartRow])
     777           0 :                                     pHeight[nRow-nStartRow] = nCjkHeight;
     778             :                             }
     779          57 :                             else if ( nScript == SCRIPTTYPE_COMPLEX )
     780             :                             {
     781           0 :                                 if ( nCtlHeight == 0 )
     782           0 :                                     nCtlHeight = lcl_GetAttribHeight( *pPattern, ATTR_CTL_FONT_HEIGHT );
     783           0 :                                 if (nCtlHeight > pHeight[nRow-nStartRow])
     784           0 :                                     pHeight[nRow-nStartRow] = nCtlHeight;
     785             :                             }
     786             :                             else
     787             :                             {
     788          57 :                                 if ( nLatHeight == 0 )
     789           0 :                                     nLatHeight = lcl_GetAttribHeight( *pPattern, ATTR_FONT_HEIGHT );
     790          57 :                                 if (nLatHeight > pHeight[nRow-nStartRow])
     791           0 :                                     pHeight[nRow-nStartRow] = nLatHeight;
     792             :                             }
     793             :                         }
     794        4908 :                         ++nIndex;
     795             :                     }
     796             :                 }
     797             :             }
     798             : 
     799      263382 :             if (!bStdOnly)                      // belegte Zellen suchen
     800             :             {
     801          16 :                 ScNeededSizeOptions aOptions;
     802             : 
     803             :                 SCSIZE nIndex;
     804          16 :                 Search(nStart,nIndex);
     805          48 :                 while ( (nIndex < maItems.size()) ? ((nRow=maItems[nIndex].nRow) <= nEnd) : false )
     806             :                 {
     807             :                     //  Zellhoehe nur berechnen, wenn sie spaeter auch gebraucht wird (#37928#)
     808             : 
     809          16 :                     if ( bShrink || !(pDocument->GetRowFlags(nRow, nTab) & CR_MANUALSIZE) )
     810             :                     {
     811          16 :                         aOptions.pPattern = pPattern;
     812             :                         sal_uInt16 nHeight = (sal_uInt16)
     813             :                                 ( GetNeededSize( nRow, pDev, nPPTX, nPPTY,
     814          16 :                                                     rZoomX, rZoomY, false, aOptions ) / nPPTY );
     815          16 :                         if (nHeight > pHeight[nRow-nStartRow])
     816          16 :                             pHeight[nRow-nStartRow] = nHeight;
     817             :                     }
     818          16 :                     ++nIndex;
     819             :                 }
     820             :             }
     821             :         }
     822             : 
     823      263391 :         if (nNextEnd > 0)
     824             :         {
     825          30 :             nStart = nEnd + 1;
     826          30 :             nEnd = nNextEnd;
     827          30 :             nNextEnd = 0;
     828             :         }
     829             :         else
     830      263361 :             pPattern = aIter.Next(nStart,nEnd);
     831             :     }
     832      263168 : }
     833             : 
     834           0 : bool ScColumn::GetNextSpellingCell(SCROW& nRow, bool bInSel, const ScMarkData& rData) const
     835             : {
     836           0 :     bool bStop = false;
     837             :     CellType eCellType;
     838             :     SCSIZE nIndex;
     839           0 :     if (!bInSel && Search(nRow, nIndex))
     840             :     {
     841           0 :         eCellType = GetCellType(nRow);
     842           0 :         if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
     843           0 :              !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
     844           0 :                pDocument->IsTabProtected(nTab)) )
     845           0 :                 return true;
     846             :     }
     847           0 :     while (!bStop)
     848             :     {
     849           0 :         if (bInSel)
     850             :         {
     851           0 :             nRow = rData.GetNextMarked(nCol, nRow, false);
     852           0 :             if (!ValidRow(nRow))
     853             :             {
     854           0 :                 nRow = MAXROW+1;
     855           0 :                 bStop = true;
     856             :             }
     857             :             else
     858             :             {
     859           0 :                 eCellType = GetCellType(nRow);
     860           0 :                 if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
     861           0 :                      !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
     862           0 :                        pDocument->IsTabProtected(nTab)) )
     863           0 :                         return true;
     864             :                 else
     865           0 :                     nRow++;
     866             :             }
     867             :         }
     868           0 :         else if (GetNextDataPos(nRow))
     869             :         {
     870           0 :             eCellType = GetCellType(nRow);
     871           0 :             if ( (eCellType == CELLTYPE_STRING || eCellType == CELLTYPE_EDIT) &&
     872           0 :                  !(HasAttrib( nRow, nRow, HASATTR_PROTECTED) &&
     873           0 :                    pDocument->IsTabProtected(nTab)) )
     874           0 :                     return true;
     875             :             else
     876           0 :                 nRow++;
     877             :         }
     878             :         else
     879             :         {
     880           0 :             nRow = MAXROW+1;
     881           0 :             bStop = true;
     882             :         }
     883             :     }
     884           0 :     return false;
     885             : }
     886             : 
     887             : // =========================================================================================
     888             : 
     889           0 : void ScColumn::RemoveAutoSpellObj()
     890             : {
     891           0 :     ScTabEditEngine* pEngine = NULL;
     892             : 
     893           0 :     for (SCSIZE i=0; i<maItems.size(); i++)
     894           0 :         if ( maItems[i].pCell->GetCellType() == CELLTYPE_EDIT )
     895             :         {
     896           0 :             ScEditCell* pOldCell = (ScEditCell*) maItems[i].pCell;
     897           0 :             const EditTextObject* pData = pOldCell->GetData();
     898             :             //  keine Abfrage auf HasOnlineSpellErrors, damit es auch
     899             :             //  nach dem Laden funktioniert
     900             : 
     901             :             //  Fuer den Test auf harte Formatierung (ScEditAttrTester) sind die Defaults
     902             :             //  in der EditEngine unwichtig. Wenn der Tester spaeter einmal gleiche
     903             :             //  Attribute in Default und harter Formatierung erkennen und weglassen sollte,
     904             :             //  muessten an der EditEngine zu jeder Zelle die richtigen Defaults gesetzt
     905             :             //  werden!
     906             : 
     907             :             //  auf Attribute testen
     908           0 :             if ( !pEngine )
     909           0 :                 pEngine = new ScTabEditEngine(pDocument);
     910           0 :             pEngine->SetText( *pData );
     911           0 :             ScEditAttrTester aTester( pEngine );
     912           0 :             if ( aTester.NeedsObject() )                    // nur Spell-Errors entfernen
     913             :             {
     914           0 :                 EditTextObject* pNewData = pEngine->CreateTextObject(); // ohne BIGOBJ
     915           0 :                 pOldCell->SetData( pNewData, pEngine->GetEditTextObjectPool() );
     916           0 :                 delete pNewData;
     917             :             }
     918             :             else                                            // String erzeugen
     919             :             {
     920           0 :                 String aText = ScEditUtil::GetSpaceDelimitedString( *pEngine );
     921           0 :                 ScBaseCell* pNewCell = new ScStringCell( aText );
     922           0 :                 pNewCell->TakeBroadcaster( pOldCell->ReleaseBroadcaster() );
     923           0 :                 maItems[i].pCell = pNewCell;
     924           0 :                 delete pOldCell;
     925           0 :             }
     926             :         }
     927             : 
     928           0 :     delete pEngine;
     929           0 : }
     930             : 
     931           0 : void ScColumn::RemoveEditAttribs( SCROW nStartRow, SCROW nEndRow )
     932             : {
     933           0 :     ScFieldEditEngine* pEngine = NULL;
     934             : 
     935             :     SCSIZE i;
     936           0 :     Search( nStartRow, i );
     937           0 :     for (; i<maItems.size() && maItems[i].nRow <= nEndRow; i++)
     938           0 :         if ( maItems[i].pCell->GetCellType() == CELLTYPE_EDIT )
     939             :         {
     940           0 :             ScEditCell* pOldCell = (ScEditCell*) maItems[i].pCell;
     941           0 :             const EditTextObject* pData = pOldCell->GetData();
     942             : 
     943             :             //  Fuer den Test auf harte Formatierung (ScEditAttrTester) sind die Defaults
     944             :             //  in der EditEngine unwichtig. Wenn der Tester spaeter einmal gleiche
     945             :             //  Attribute in Default und harter Formatierung erkennen und weglassen sollte,
     946             :             //  muessten an der EditEngine zu jeder Zelle die richtigen Defaults gesetzt
     947             :             //  werden!
     948             : 
     949             :             //  auf Attribute testen
     950           0 :             if ( !pEngine )
     951             :             {
     952           0 :                 pEngine = new ScFieldEditEngine(pDocument, pDocument->GetEditPool());
     953             :                 //  EE_CNTRL_ONLINESPELLING falls schon Fehler drin sind
     954           0 :                 pEngine->SetControlWord( pEngine->GetControlWord() | EE_CNTRL_ONLINESPELLING );
     955           0 :                 pDocument->ApplyAsianEditSettings( *pEngine );
     956             :             }
     957           0 :             pEngine->SetText( *pData );
     958           0 :             sal_uInt16 nParCount = pEngine->GetParagraphCount();
     959           0 :             for (sal_uInt16 nPar=0; nPar<nParCount; nPar++)
     960             :             {
     961           0 :                 pEngine->QuickRemoveCharAttribs( nPar );
     962           0 :                 const SfxItemSet& rOld = pEngine->GetParaAttribs( nPar );
     963           0 :                 if ( rOld.Count() )
     964             :                 {
     965           0 :                     SfxItemSet aNew( *rOld.GetPool(), rOld.GetRanges() );   // leer
     966           0 :                     pEngine->SetParaAttribs( nPar, aNew );
     967             :                 }
     968             :             }
     969             :             //  URL-Felder in Text wandeln (andere gibt's nicht, darum pType=0)
     970           0 :             pEngine->RemoveFields( true );
     971             : 
     972           0 :             bool bSpellErrors = pEngine->HasOnlineSpellErrors();
     973           0 :             bool bNeedObject = bSpellErrors || nParCount>1;         // Errors/Absaetze behalten
     974             :             //  ScEditAttrTester nicht mehr noetig, Felder sind raus
     975             : 
     976           0 :             if ( bNeedObject )                                      // bleibt Edit-Zelle
     977             :             {
     978           0 :                 sal_uInt32 nCtrl = pEngine->GetControlWord();
     979           0 :                 sal_uInt32 nWantBig = bSpellErrors ? EE_CNTRL_ALLOWBIGOBJS : 0;
     980           0 :                 if ( ( nCtrl & EE_CNTRL_ALLOWBIGOBJS ) != nWantBig )
     981           0 :                     pEngine->SetControlWord( (nCtrl & ~EE_CNTRL_ALLOWBIGOBJS) | nWantBig );
     982           0 :                 EditTextObject* pNewData = pEngine->CreateTextObject();
     983           0 :                 pOldCell->SetData( pNewData, pEngine->GetEditTextObjectPool() );
     984           0 :                 delete pNewData;
     985             :             }
     986             :             else                                            // String erzeugen
     987             :             {
     988           0 :                 String aText = ScEditUtil::GetSpaceDelimitedString( *pEngine );
     989           0 :                 ScBaseCell* pNewCell = new ScStringCell( aText );
     990           0 :                 pNewCell->TakeBroadcaster( pOldCell->ReleaseBroadcaster() );
     991           0 :                 maItems[i].pCell = pNewCell;
     992           0 :                 delete pOldCell;
     993             :             }
     994             :         }
     995             : 
     996           0 :     delete pEngine;
     997           0 : }
     998             : 
     999             : // =========================================================================================
    1000             : 
    1001           0 : bool ScColumn::TestTabRefAbs(SCTAB nTable) const
    1002             : {
    1003           0 :     bool bRet = false;
    1004           0 :     if ( !maItems.empty() )
    1005           0 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1006           0 :             if ( maItems[i].pCell->GetCellType() == CELLTYPE_FORMULA )
    1007           0 :                 if (((ScFormulaCell*)maItems[i].pCell)->TestTabRefAbs(nTable))
    1008           0 :                     bRet = true;
    1009           0 :     return bRet;
    1010             : }
    1011             : 
    1012             : // =========================================================================================
    1013             : 
    1014       23955 : ScColumnIterator::ScColumnIterator( const ScColumn* pCol, SCROW nStart, SCROW nEnd ) :
    1015             :     pColumn( pCol ),
    1016             :     nTop( nStart ),
    1017       23955 :     nBottom( nEnd )
    1018             : {
    1019       23955 :     pColumn->Search( nTop, nPos );
    1020       23955 : }
    1021             : 
    1022       23955 : ScColumnIterator::~ScColumnIterator()
    1023             : {
    1024       23955 : }
    1025             : 
    1026       24255 : bool ScColumnIterator::Next( SCROW& rRow, ScBaseCell*& rpCell )
    1027             : {
    1028       24255 :     if ( nPos < pColumn->maItems.size() )
    1029             :     {
    1030         388 :         rRow = pColumn->maItems[nPos].nRow;
    1031         388 :         if ( rRow <= nBottom )
    1032             :         {
    1033         300 :             rpCell = pColumn->maItems[nPos].pCell;
    1034         300 :             ++nPos;
    1035         300 :             return true;
    1036             :         }
    1037             :     }
    1038             : 
    1039       23955 :     rRow = 0;
    1040       23955 :     rpCell = NULL;
    1041       23955 :     return false;
    1042             : }
    1043             : 
    1044           0 : SCSIZE ScColumnIterator::GetIndex() const           // Index zur letzen abgefragten Zelle
    1045             : {
    1046           0 :     return nPos - 1;        // bei Next ist Pos hochgezaehlt worden
    1047             : }
    1048             : 
    1049             : // -----------------------------------------------------------------------------------------
    1050             : 
    1051          67 : ScMarkedDataIter::ScMarkedDataIter( const ScColumn* pCol, const ScMarkData* pMarkData,
    1052             :                                     bool bAllIfNone ) :
    1053             :     pColumn( pCol ),
    1054             :     pMarkIter( NULL ),
    1055             :     bNext( true ),
    1056          67 :     bAll( bAllIfNone )
    1057             : {
    1058          67 :     if (pMarkData && pMarkData->IsMultiMarked())
    1059          67 :         pMarkIter = new ScMarkArrayIter( pMarkData->GetArray() + pCol->GetCol() );
    1060          67 : }
    1061             : 
    1062          67 : ScMarkedDataIter::~ScMarkedDataIter()
    1063             : {
    1064          67 :     delete pMarkIter;
    1065          67 : }
    1066             : 
    1067        2672 : bool ScMarkedDataIter::Next( SCSIZE& rIndex )
    1068             : {
    1069        2672 :     bool bFound = false;
    1070        2605 :     do
    1071             :     {
    1072        2672 :         if (bNext)
    1073             :         {
    1074          67 :             if (!pMarkIter || !pMarkIter->Next( nTop, nBottom ))
    1075             :             {
    1076           0 :                 if (bAll)                   // ganze Spalte
    1077             :                 {
    1078           0 :                     nTop    = 0;
    1079           0 :                     nBottom = MAXROW;
    1080             :                 }
    1081             :                 else
    1082           0 :                     return false;
    1083             :             }
    1084          67 :             pColumn->Search( nTop, nPos );
    1085          67 :             bNext = false;
    1086          67 :             bAll  = false;                  // nur beim ersten Versuch
    1087             :         }
    1088             : 
    1089        2672 :         if ( nPos >= pColumn->maItems.size() )
    1090          67 :             return false;
    1091             : 
    1092        2605 :         if ( pColumn->maItems[nPos].nRow <= nBottom )
    1093        2605 :             bFound = true;
    1094             :         else
    1095           0 :             bNext = true;
    1096             :     }
    1097        2605 :     while (!bFound);
    1098             : 
    1099        2605 :     rIndex = nPos++;
    1100        2605 :     return true;
    1101             : }
    1102             : 
    1103             : 
    1104             : //------------
    1105             : 
    1106       78214 : bool ScColumn::IsEmptyData() const
    1107             : {
    1108       78214 :     return (maItems.empty());
    1109             : }
    1110             : 
    1111       95494 : bool ScColumn::IsEmptyVisData() const
    1112             : {
    1113       95494 :     if ( maItems.empty() )
    1114       95287 :         return true;
    1115             :     else
    1116             :     {
    1117         207 :         bool bVisData = false;
    1118             :         SCSIZE i;
    1119         414 :         for (i=0; i<maItems.size() && !bVisData; i++)
    1120             :         {
    1121         207 :             if(!maItems[i].pCell->IsBlank())
    1122         207 :                 bVisData = true;
    1123             :         }
    1124         207 :         return !bVisData;
    1125             :     }
    1126             : }
    1127             : 
    1128           0 : SCSIZE ScColumn::VisibleCount( SCROW nStartRow, SCROW nEndRow ) const
    1129             : {
    1130             :     //  Notizen werden nicht mitgezaehlt
    1131             : 
    1132           0 :     SCSIZE nVisCount = 0;
    1133             :     SCSIZE nIndex;
    1134           0 :     Search( nStartRow, nIndex );
    1135           0 :     while ( nIndex < maItems.size() && maItems[nIndex].nRow <= nEndRow )
    1136             :     {
    1137           0 :         if ( maItems[nIndex].nRow >= nStartRow )
    1138             :         {
    1139           0 :             ++nVisCount;
    1140             :         }
    1141           0 :         ++nIndex;
    1142             :     }
    1143           0 :     return nVisCount;
    1144             : }
    1145             : 
    1146       80337 : SCROW ScColumn::GetLastVisDataPos() const
    1147             : {
    1148       80337 :     SCROW nRet = 0;
    1149       80337 :     if ( !maItems.empty() )
    1150             :     {
    1151             :         SCSIZE i;
    1152         339 :         bool bFound = false;
    1153        1017 :         for (i=maItems.size(); i>0 && !bFound; )
    1154             :         {
    1155         339 :             --i;
    1156         339 :             if(!maItems[i].pCell->IsBlank())
    1157             :             {
    1158         339 :                 bFound = true;
    1159         339 :                 nRet = maItems[i].nRow;
    1160             :             }
    1161             :         }
    1162             :     }
    1163       80337 :     return nRet;
    1164             : }
    1165             : 
    1166           4 : SCROW ScColumn::GetFirstVisDataPos() const
    1167             : {
    1168           4 :     SCROW nRet = 0;
    1169           4 :     if ( !maItems.empty() )
    1170             :     {
    1171             :         SCSIZE i;
    1172           4 :         bool bFound = false;
    1173           8 :         for (i=0; i<maItems.size() && !bFound; i++)
    1174             :         {
    1175           4 :             bFound = true;
    1176           4 :             nRet = maItems[i].nRow;
    1177             :         }
    1178             :     }
    1179           4 :     return nRet;
    1180             : }
    1181             : 
    1182        1038 : bool ScColumn::HasVisibleDataAt(SCROW nRow) const
    1183             : {
    1184             :     SCSIZE nIndex;
    1185        1038 :     if (Search(nRow, nIndex))
    1186          12 :         if (!maItems[nIndex].pCell->IsBlank())
    1187          12 :             return true;
    1188             : 
    1189        1026 :     return false;
    1190             : }
    1191             : 
    1192           2 : bool ScColumn::IsEmptyAttr() const
    1193             : {
    1194           2 :     if (pAttrArray)
    1195           2 :         return pAttrArray->IsEmpty();
    1196             :     else
    1197           0 :         return true;
    1198             : }
    1199             : 
    1200           2 : bool ScColumn::IsEmpty() const
    1201             : {
    1202           2 :     return (IsEmptyData() && IsEmptyAttr());
    1203             : }
    1204             : 
    1205        2479 : bool ScColumn::IsEmptyBlock(SCROW nStartRow, SCROW nEndRow) const
    1206             : {
    1207        2479 :     if ( maItems.empty() )
    1208        2464 :         return true;
    1209             : 
    1210             :     SCSIZE nIndex;
    1211          15 :     Search( nStartRow, nIndex );
    1212          30 :     while ( nIndex < maItems.size() && maItems[nIndex].nRow <= nEndRow )
    1213             :     {
    1214          13 :         if ( !maItems[nIndex].pCell->IsBlank() )   // found a cell
    1215          13 :             return false;                           // not empty
    1216           0 :         ++nIndex;
    1217             :     }
    1218           2 :     return true;                                    // no cell found
    1219             : }
    1220             : 
    1221           0 : SCSIZE ScColumn::GetEmptyLinesInBlock( SCROW nStartRow, SCROW nEndRow, ScDirection eDir ) const
    1222             : {
    1223           0 :     SCSIZE nLines = 0;
    1224           0 :     bool bFound = false;
    1225             :     SCSIZE i;
    1226           0 :     if ( !maItems.empty() )
    1227             :     {
    1228           0 :         if (eDir == DIR_BOTTOM)
    1229             :         {
    1230           0 :             i = maItems.size();
    1231           0 :             while (!bFound && (i > 0))
    1232             :             {
    1233           0 :                 i--;
    1234           0 :                 if ( maItems[i].nRow < nStartRow )
    1235           0 :                     break;
    1236           0 :                 bFound = maItems[i].nRow <= nEndRow && !maItems[i].pCell->IsBlank();
    1237             :             }
    1238           0 :             if (bFound)
    1239           0 :                 nLines = static_cast<SCSIZE>(nEndRow - maItems[i].nRow);
    1240             :             else
    1241           0 :                 nLines = static_cast<SCSIZE>(nEndRow - nStartRow);
    1242             :         }
    1243           0 :         else if (eDir == DIR_TOP)
    1244             :         {
    1245           0 :             i = 0;
    1246           0 :             while (!bFound && (i < maItems.size()))
    1247             :             {
    1248           0 :                 if ( maItems[i].nRow > nEndRow )
    1249           0 :                     break;
    1250           0 :                 bFound = maItems[i].nRow >= nStartRow && !maItems[i].pCell->IsBlank();
    1251           0 :                 i++;
    1252             :             }
    1253           0 :             if (bFound)
    1254           0 :                 nLines = static_cast<SCSIZE>(maItems[i-1].nRow - nStartRow);
    1255             :             else
    1256           0 :                 nLines = static_cast<SCSIZE>(nEndRow - nStartRow);
    1257             :         }
    1258             :     }
    1259             :     else
    1260           0 :         nLines = static_cast<SCSIZE>(nEndRow - nStartRow);
    1261           0 :     return nLines;
    1262             : }
    1263             : 
    1264         112 : SCROW ScColumn::GetFirstDataPos() const
    1265             : {
    1266         112 :     if ( !maItems.empty() )
    1267         112 :         return maItems[0].nRow;
    1268             :     else
    1269           0 :         return 0;
    1270             : }
    1271             : 
    1272         809 : SCROW ScColumn::GetLastDataPos() const
    1273             : {
    1274         809 :     if ( !maItems.empty() )
    1275         729 :         return maItems.back().nRow;
    1276             :     else
    1277          80 :         return 0;
    1278             : }
    1279             : 
    1280           0 : bool ScColumn::GetPrevDataPos(SCROW& rRow) const
    1281             : {
    1282           0 :     bool bFound = false;
    1283           0 :     SCSIZE i = maItems.size();
    1284           0 :     while (!bFound && (i > 0))
    1285             :     {
    1286           0 :         --i;
    1287           0 :         bFound = (maItems[i].nRow < rRow);
    1288           0 :         if (bFound)
    1289           0 :             rRow = maItems[i].nRow;
    1290             :     }
    1291           0 :     return bFound;
    1292             : }
    1293             : 
    1294         664 : bool ScColumn::GetNextDataPos(SCROW& rRow) const        // greater than rRow
    1295             : {
    1296             :     SCSIZE nIndex;
    1297         664 :     if (Search( rRow, nIndex ))
    1298         657 :         ++nIndex;                   // next cell
    1299             : 
    1300         664 :     bool bMore = ( nIndex < maItems.size() );
    1301         664 :     if ( bMore )
    1302         603 :         rRow = maItems[nIndex].nRow;
    1303         664 :     return bMore;
    1304             : }
    1305             : 
    1306           9 : SCROW ScColumn::FindNextVisibleRow(SCROW nRow, bool bForward) const
    1307             : {
    1308           9 :     if(bForward)
    1309             :     {
    1310           9 :         nRow++;
    1311           9 :         SCROW nEndRow = 0;
    1312           9 :         bool bHidden = pDocument->RowHidden(nRow, nTab, NULL, &nEndRow);
    1313           9 :         if(bHidden)
    1314           2 :             return std::min<SCROW>(MAXROW, nEndRow + 1);
    1315             :         else
    1316           7 :             return nRow;
    1317             :     }
    1318             :     else
    1319             :     {
    1320           0 :         nRow--;
    1321           0 :         SCROW nStartRow = MAXROW;
    1322           0 :         bool bHidden = pDocument->RowHidden(nRow, nTab, &nStartRow, NULL);
    1323           0 :         if(bHidden)
    1324           0 :             return std::max<SCROW>(0, nStartRow - 1);
    1325             :         else
    1326           0 :             return nRow;
    1327             :     }
    1328             : }
    1329             : 
    1330           4 : SCROW ScColumn::FindNextVisibleRowWithContent(SCROW nRow, bool bForward) const
    1331             : {
    1332           4 :     if(bForward)
    1333             :     {
    1334           0 :         do
    1335             :         {
    1336           4 :             nRow++;
    1337           4 :             SCROW nEndRow = 0;
    1338           4 :             bool bHidden = pDocument->RowHidden(nRow, nTab, NULL, &nEndRow);
    1339           4 :             if(bHidden)
    1340             :             {
    1341           1 :                 nRow = nEndRow + 1;
    1342           1 :                 if(nRow >= MAXROW)
    1343           0 :                     return MAXROW;
    1344             :             }
    1345             : 
    1346             :             SCSIZE nIndex;
    1347           4 :             bool bThere = Search( nRow, nIndex );
    1348           4 :             if( bThere && !maItems[nIndex].pCell->IsBlank())
    1349           3 :                 return nRow;
    1350           1 :             else if(nIndex >= maItems.size())
    1351           1 :                 return MAXROW;
    1352             :             else
    1353             :             {
    1354           0 :                 if(bThere)
    1355           0 :                     nRow = maItems[nIndex+1].nRow - 1;
    1356             :                 else
    1357           0 :                     nRow = maItems[nIndex].nRow - 1;
    1358             :             }
    1359             :         }
    1360             :         while(nRow < MAXROW);
    1361             : 
    1362           0 :         return MAXROW;
    1363             :     }
    1364             :     else
    1365             :     {
    1366           0 :         do
    1367             :         {
    1368           0 :             nRow--;
    1369           0 :             SCROW nStartRow = MAXROW;
    1370           0 :             bool bHidden = pDocument->RowHidden(nRow, nTab, &nStartRow, NULL);
    1371           0 :             if(bHidden)
    1372             :             {
    1373           0 :                 nRow = nStartRow - 1;
    1374           0 :                 if(nRow <= 0)
    1375           0 :                     return 0;
    1376             :             }
    1377             : 
    1378             :             SCSIZE nIndex;
    1379           0 :             bool bThere = Search( nRow, nIndex );
    1380           0 :             if(bThere && !maItems[nIndex].pCell->IsBlank())
    1381           0 :                 return nRow;
    1382           0 :             else if(nIndex == 0)
    1383           0 :                 return 0;
    1384             :             else
    1385           0 :                 nRow = maItems[nIndex-1].nRow + 1;
    1386             :         }
    1387             :         while(nRow > 0);
    1388             : 
    1389           0 :         return 0;
    1390             :     }
    1391             : }
    1392             : 
    1393           7 : void ScColumn::FindDataAreaPos(SCROW& rRow, bool bDown) const
    1394             : {
    1395             :     // check if we are in a data area
    1396             :     SCSIZE nIndex;
    1397           7 :     bool bThere = Search(rRow, nIndex);
    1398           7 :     if (bThere && maItems[nIndex].pCell->IsBlank())
    1399           0 :         bThere = false;
    1400             : 
    1401           7 :     size_t nLastIndex = maItems.size() - 1;
    1402           7 :     if (bThere)
    1403             :     {
    1404           6 :         SCROW nNextRow = FindNextVisibleRow(rRow, bDown);
    1405             :         SCSIZE nNewIndex;
    1406           6 :         bool bNextThere = Search(nNextRow, nNewIndex);
    1407           6 :         if(bNextThere && maItems[nNewIndex].pCell->IsBlank())
    1408           0 :             bNextThere = false;
    1409             : 
    1410           6 :         if(bNextThere)
    1411             :         {
    1412             :             SCROW nLastRow;
    1413           3 :             nLastRow = nNextRow;
    1414           3 :             do
    1415             :             {
    1416           3 :                 nNextRow = FindNextVisibleRow(nLastRow, bDown);
    1417           3 :                 bNextThere = Search(nNextRow, nNewIndex);
    1418           3 :                 if(!bNextThere || maItems[nNewIndex].pCell->IsBlank())
    1419           3 :                     bNextThere = false;
    1420             :                 else
    1421           0 :                     nLastRow = nNextRow;
    1422             :             }
    1423             :             while(bNextThere && nNewIndex < nLastIndex && nNewIndex > 0);
    1424             : 
    1425           3 :             rRow = nLastRow;
    1426             :         }
    1427             :         else
    1428             :         {
    1429           3 :             rRow = FindNextVisibleRowWithContent(nNextRow, bDown);
    1430             :         }
    1431             :     }
    1432             :     else
    1433             :     {
    1434           1 :         rRow = FindNextVisibleRowWithContent(rRow, bDown);
    1435             :     }
    1436           7 : }
    1437             : 
    1438         231 : bool ScColumn::HasDataAt(SCROW nRow) const
    1439             : {
    1440             :         //  immer nur sichtbare interessant ?
    1441             :         //! dann HasVisibleDataAt raus
    1442             : 
    1443             :     SCSIZE nIndex;
    1444         231 :     if (Search(nRow, nIndex))
    1445         209 :         if (!maItems[nIndex].pCell->IsBlank())
    1446         209 :             return true;
    1447             : 
    1448          22 :     return false;
    1449             : 
    1450             : }
    1451             : 
    1452        2046 : bool ScColumn::IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const
    1453             : {
    1454        2046 :     if (pAttrArray && rCol.pAttrArray)
    1455        2046 :         return pAttrArray->IsAllEqual( *rCol.pAttrArray, nStartRow, nEndRow );
    1456             :     else
    1457           0 :         return !pAttrArray && !rCol.pAttrArray;
    1458             : }
    1459             : 
    1460           0 : bool ScColumn::IsVisibleAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const
    1461             : {
    1462           0 :     if (pAttrArray && rCol.pAttrArray)
    1463           0 :         return pAttrArray->IsVisibleEqual( *rCol.pAttrArray, nStartRow, nEndRow );
    1464             :     else
    1465           0 :         return !pAttrArray && !rCol.pAttrArray;
    1466             : }
    1467             : 
    1468        6144 : bool ScColumn::GetFirstVisibleAttr( SCROW& rFirstRow ) const
    1469             : {
    1470        6144 :     if (pAttrArray)
    1471        6144 :         return pAttrArray->GetFirstVisibleAttr( rFirstRow );
    1472             :     else
    1473           0 :         return false;
    1474             : }
    1475             : 
    1476       80134 : bool ScColumn::GetLastVisibleAttr( SCROW& rLastRow, bool bFullFormattedArea ) const
    1477             : {
    1478       80134 :     if (pAttrArray)
    1479             :     {
    1480             :         // row of last cell is needed
    1481       80134 :         SCROW nLastData = GetLastVisDataPos();    // always including notes, 0 if none
    1482             : 
    1483       80134 :         return pAttrArray->GetLastVisibleAttr( rLastRow, nLastData, bFullFormattedArea );
    1484             :     }
    1485             :     else
    1486           0 :         return false;
    1487             : }
    1488             : 
    1489           0 : bool ScColumn::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const
    1490             : {
    1491           0 :     if (pAttrArray)
    1492           0 :         return pAttrArray->HasVisibleAttrIn( nStartRow, nEndRow );
    1493             :     else
    1494           0 :         return false;
    1495             : }
    1496             : 
    1497           0 : void ScColumn::FindUsed( SCROW nStartRow, SCROW nEndRow, bool* pUsed ) const
    1498             : {
    1499           0 :     SCROW nRow = 0;
    1500             :     SCSIZE nIndex;
    1501           0 :     Search( nStartRow, nIndex );
    1502           0 :     while ( (nIndex < maItems.size()) ? ((nRow=maItems[nIndex].nRow) <= nEndRow) : false )
    1503             :     {
    1504           0 :         pUsed[nRow-nStartRow] = true;
    1505           0 :         ++nIndex;
    1506             :     }
    1507           0 : }
    1508             : 
    1509        5028 : void ScColumn::StartListening( SvtListener& rLst, SCROW nRow )
    1510             : {
    1511        5028 :     SvtBroadcaster* pBC = NULL;
    1512             :     ScBaseCell* pCell;
    1513             : 
    1514             :     SCSIZE nIndex;
    1515        5028 :     if (Search(nRow,nIndex))
    1516             :     {
    1517        5005 :         pCell = maItems[nIndex].pCell;
    1518        5005 :         pBC = pCell->GetBroadcaster();
    1519             :     }
    1520             :     else
    1521             :     {
    1522          23 :         pCell = new ScNoteCell;
    1523          23 :         Insert(nRow, pCell);
    1524             :     }
    1525             : 
    1526        5028 :     if (!pBC)
    1527             :     {
    1528        3637 :         pBC = new SvtBroadcaster;
    1529        3637 :         pCell->TakeBroadcaster(pBC);
    1530             :     }
    1531        5028 :     rLst.StartListening(*pBC);
    1532        5028 : }
    1533             : 
    1534           0 : void ScColumn::MoveListeners( SvtBroadcaster& rSource, SCROW nDestRow )
    1535             : {
    1536           0 :     SvtBroadcaster* pBC = NULL;
    1537             :     ScBaseCell* pCell;
    1538             : 
    1539             :     SCSIZE nIndex;
    1540           0 :     if (Search(nDestRow,nIndex))
    1541             :     {
    1542           0 :         pCell = maItems[nIndex].pCell;
    1543           0 :         pBC = pCell->GetBroadcaster();
    1544             :     }
    1545             :     else
    1546             :     {
    1547           0 :         pCell = new ScNoteCell;
    1548           0 :         Insert(nDestRow, pCell);
    1549             :     }
    1550             : 
    1551           0 :     if (!pBC)
    1552             :     {
    1553           0 :         pBC = new SvtBroadcaster;
    1554           0 :         pCell->TakeBroadcaster(pBC);
    1555             :     }
    1556             : 
    1557           0 :     if (rSource.HasListeners())
    1558             :     {
    1559           0 :         SvtListenerIter aIter( rSource);
    1560           0 :         for (SvtListener* pLst = aIter.GoStart(); pLst; pLst = aIter.GoNext())
    1561             :         {
    1562           0 :             pLst->StartListening( *pBC);
    1563           0 :             pLst->EndListening( rSource);
    1564           0 :         }
    1565             :     }
    1566           0 : }
    1567             : 
    1568         176 : void ScColumn::EndListening( SvtListener& rLst, SCROW nRow )
    1569             : {
    1570             :     SCSIZE nIndex;
    1571         176 :     if (Search(nRow,nIndex))
    1572             :     {
    1573         174 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    1574         174 :         SvtBroadcaster* pBC = pCell->GetBroadcaster();
    1575         174 :         if (pBC)
    1576             :         {
    1577         168 :             rLst.EndListening(*pBC);
    1578             : 
    1579         168 :             if (!pBC->HasListeners())
    1580             :             {
    1581         145 :                 if (pCell->IsBlank())
    1582          43 :                     DeleteAtIndex(nIndex);
    1583             :                 else
    1584         102 :                     pCell->DeleteBroadcaster();
    1585             :             }
    1586             :         }
    1587             :     }
    1588         176 : }
    1589             : 
    1590           0 : void ScColumn::CompileDBFormula()
    1591             : {
    1592           0 :     if ( !maItems.empty() )
    1593           0 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1594             :         {
    1595           0 :             ScBaseCell* pCell = maItems[i].pCell;
    1596           0 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1597           0 :                 ((ScFormulaCell*) pCell)->CompileDBFormula();
    1598             :         }
    1599           0 : }
    1600             : 
    1601           0 : void ScColumn::CompileDBFormula( bool bCreateFormulaString )
    1602             : {
    1603           0 :     if ( !maItems.empty() )
    1604           0 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1605             :         {
    1606           0 :             ScBaseCell* pCell = maItems[i].pCell;
    1607           0 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1608           0 :                 ((ScFormulaCell*) pCell)->CompileDBFormula( bCreateFormulaString );
    1609             :         }
    1610           0 : }
    1611             : 
    1612       36864 : void ScColumn::CompileNameFormula( bool bCreateFormulaString )
    1613             : {
    1614       36864 :     if ( !maItems.empty() )
    1615         759 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1616             :         {
    1617         691 :             ScBaseCell* pCell = maItems[i].pCell;
    1618         691 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1619          34 :                 ((ScFormulaCell*) pCell)->CompileNameFormula( bCreateFormulaString );
    1620             :         }
    1621       36864 : }
    1622             : 
    1623           0 : void ScColumn::CompileColRowNameFormula()
    1624             : {
    1625           0 :     if ( !maItems.empty() )
    1626           0 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1627             :         {
    1628           0 :             ScBaseCell* pCell = maItems[i].pCell;
    1629           0 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1630           0 :                 ((ScFormulaCell*) pCell)->CompileColRowNameFormula();
    1631             :         }
    1632           0 : }
    1633             : 
    1634           0 : static void lcl_UpdateSubTotal( ScFunctionData& rData, const ScBaseCell* pCell )
    1635             : {
    1636           0 :     double nValue = 0.0;
    1637           0 :     bool bVal = false;
    1638           0 :     bool bCell = true;
    1639           0 :     switch (pCell->GetCellType())
    1640             :     {
    1641             :         case CELLTYPE_VALUE:
    1642           0 :             nValue = ((ScValueCell*)pCell)->GetValue();
    1643           0 :             bVal = true;
    1644           0 :             break;
    1645             :         case CELLTYPE_FORMULA:
    1646             :             {
    1647           0 :                 if ( rData.eFunc != SUBTOTAL_FUNC_CNT2 )        // da interessiert's nicht
    1648             :                 {
    1649           0 :                     ScFormulaCell* pFC = (ScFormulaCell*)pCell;
    1650           0 :                     if ( pFC->GetErrCode() )
    1651             :                     {
    1652           0 :                         if ( rData.eFunc != SUBTOTAL_FUNC_CNT ) // fuer Anzahl einfach weglassen
    1653           0 :                             rData.bError = true;
    1654             :                     }
    1655           0 :                     else if (pFC->IsValue())
    1656             :                     {
    1657           0 :                         nValue = pFC->GetValue();
    1658           0 :                         bVal = true;
    1659             :                     }
    1660             :                     // sonst Text
    1661             :                 }
    1662             :             }
    1663           0 :             break;
    1664             :         case CELLTYPE_NOTE:
    1665           0 :             bCell = false;
    1666           0 :             break;
    1667             :         // bei Strings nichts
    1668             :         default:
    1669             :         {
    1670             :             // added to avoid warnings
    1671             :         }
    1672             :     }
    1673             : 
    1674           0 :     if (!rData.bError)
    1675             :     {
    1676           0 :         switch (rData.eFunc)
    1677             :         {
    1678             :             case SUBTOTAL_FUNC_SUM:
    1679             :             case SUBTOTAL_FUNC_AVE:
    1680           0 :                 if (bVal)
    1681             :                 {
    1682           0 :                     ++rData.nCount;
    1683           0 :                     if (!SubTotal::SafePlus( rData.nVal, nValue ))
    1684           0 :                         rData.bError = true;
    1685             :                 }
    1686           0 :                 break;
    1687             :             case SUBTOTAL_FUNC_CNT:             // nur Werte
    1688           0 :                 if (bVal)
    1689           0 :                     ++rData.nCount;
    1690           0 :                 break;
    1691             :             case SUBTOTAL_FUNC_CNT2:            // alle
    1692           0 :                 if (bCell)
    1693           0 :                     ++rData.nCount;
    1694           0 :                 break;
    1695             :             case SUBTOTAL_FUNC_MAX:
    1696           0 :                 if (bVal)
    1697           0 :                     if (++rData.nCount == 1 || nValue > rData.nVal )
    1698           0 :                         rData.nVal = nValue;
    1699           0 :                 break;
    1700             :             case SUBTOTAL_FUNC_MIN:
    1701           0 :                 if (bVal)
    1702           0 :                     if (++rData.nCount == 1 || nValue < rData.nVal )
    1703           0 :                         rData.nVal = nValue;
    1704           0 :                 break;
    1705             :             default:
    1706             :             {
    1707             :                 // added to avoid warnings
    1708             :             }
    1709             :         }
    1710             :     }
    1711           0 : }
    1712             : 
    1713             : //  Mehrfachselektion:
    1714           0 : void ScColumn::UpdateSelectionFunction(
    1715             :     const ScMarkData& rMark, ScFunctionData& rData, ScFlatBoolRowSegments& rHiddenRows,
    1716             :     bool bDoExclude, SCROW nExStartRow, SCROW nExEndRow) const
    1717             : {
    1718             :     SCSIZE nIndex;
    1719           0 :     ScMarkedDataIter aDataIter(this, &rMark, false);
    1720           0 :     while (aDataIter.Next( nIndex ))
    1721             :     {
    1722           0 :         SCROW nRow = maItems[nIndex].nRow;
    1723           0 :         bool bRowHidden = rHiddenRows.getValue(nRow);
    1724           0 :         if ( !bRowHidden )
    1725           0 :             if ( !bDoExclude || nRow < nExStartRow || nRow > nExEndRow )
    1726           0 :                 lcl_UpdateSubTotal( rData, maItems[nIndex].pCell );
    1727           0 :     }
    1728           0 : }
    1729             : 
    1730             : //  bei bNoMarked die Mehrfachselektion weglassen
    1731           0 : void ScColumn::UpdateAreaFunction(
    1732             :     ScFunctionData& rData, ScFlatBoolRowSegments& rHiddenRows, SCROW nStartRow, SCROW nEndRow) const
    1733             : {
    1734             :     SCSIZE nIndex;
    1735           0 :     Search( nStartRow, nIndex );
    1736           0 :     while ( nIndex<maItems.size() && maItems[nIndex].nRow<=nEndRow )
    1737             :     {
    1738           0 :         SCROW nRow = maItems[nIndex].nRow;
    1739           0 :         bool bRowHidden = rHiddenRows.getValue(nRow);
    1740           0 :         if ( !bRowHidden )
    1741           0 :             lcl_UpdateSubTotal( rData, maItems[nIndex].pCell );
    1742           0 :         ++nIndex;
    1743             :     }
    1744           0 : }
    1745             : 
    1746        5285 : sal_uInt32 ScColumn::GetWeightedCount() const
    1747             : {
    1748        5285 :     sal_uInt32 nTotal = 0;
    1749             : 
    1750             :     //  Notizen werden nicht gezaehlt
    1751             : 
    1752       19595 :     for (SCSIZE i=0; i<maItems.size(); i++)
    1753             :     {
    1754       14310 :         ScBaseCell* pCell = maItems[i].pCell;
    1755       14310 :         switch ( pCell->GetCellType() )
    1756             :         {
    1757             :             case CELLTYPE_VALUE:
    1758             :             case CELLTYPE_STRING:
    1759       14254 :                 ++nTotal;
    1760       14254 :                 break;
    1761             :             case CELLTYPE_FORMULA:
    1762          22 :                 nTotal += 5 + ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen();
    1763          22 :                 break;
    1764             :             case CELLTYPE_EDIT:
    1765          32 :                 nTotal += 50;
    1766          32 :                 break;
    1767             :             default:
    1768             :             {
    1769             :                 // added to avoid warnings
    1770             :             }
    1771             :         }
    1772             :     }
    1773             : 
    1774        5285 :     return nTotal;
    1775             : }
    1776             : 
    1777           0 : sal_uInt32 ScColumn::GetCodeCount() const
    1778             : {
    1779           0 :     sal_uInt32 nCodeCount = 0;
    1780             : 
    1781           0 :     for (SCSIZE i=0; i<maItems.size(); i++)
    1782             :     {
    1783           0 :         ScBaseCell* pCell = maItems[i].pCell;
    1784           0 :         if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1785           0 :             nCodeCount += ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen();
    1786             :     }
    1787             : 
    1788           0 :     return nCodeCount;
    1789             : }
    1790             : 
    1791             : 
    1792             : 
    1793             : 
    1794             : 
    1795             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10