LCOV - code coverage report
Current view: top level - sc/source/core/data - column3.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 489 904 54.1 %
Date: 2012-08-25 Functions: 30 42 71.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 552 1505 36.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <boost/scoped_ptr.hpp>
      30                 :            : 
      31                 :            : #include <mdds/flat_segment_tree.hpp>
      32                 :            : 
      33                 :            : #include <sfx2/objsh.hxx>
      34                 :            : #include <svl/zforlist.hxx>
      35                 :            : #include <svl/zformat.hxx>
      36                 :            : #include <svl/broadcast.hxx>
      37                 :            : 
      38                 :            : #include "scitems.hxx"
      39                 :            : #include "column.hxx"
      40                 :            : #include "cell.hxx"
      41                 :            : #include "document.hxx"
      42                 :            : #include "attarray.hxx"
      43                 :            : #include "patattr.hxx"
      44                 :            : #include "cellform.hxx"
      45                 :            : #include "typedstrdata.hxx"
      46                 :            : #include "formula/errorcodes.hxx"
      47                 :            : #include "formula/token.hxx"
      48                 :            : #include "brdcst.hxx"
      49                 :            : #include "docoptio.hxx"         // GetStdPrecision fuer GetMaxNumberStringLen
      50                 :            : #include "subtotal.hxx"
      51                 :            : #include "markdata.hxx"
      52                 :            : #include "detfunc.hxx"          // fuer Notizen bei DeleteRange
      53                 :            : #include "postit.hxx"
      54                 :            : #include "stringutil.hxx"
      55                 :            : #include "docpool.hxx"
      56                 :            : 
      57                 :            : #include <com/sun/star/i18n/LocaleDataItem.hpp>
      58                 :            : 
      59                 :            : using ::com::sun::star::i18n::LocaleDataItem;
      60                 :            : using ::rtl::OUString;
      61                 :            : using ::rtl::OUStringBuffer;
      62                 :            : 
      63                 :            : // Err527 Workaround
      64                 :            : extern const ScFormulaCell* pLastFormulaTreeTop;    // in cellform.cxx
      65                 :            : using namespace formula;
      66                 :            : // STATIC DATA -----------------------------------------------------------
      67                 :            : 
      68                 :            : bool ScColumn::bDoubleAlloc = false;    // fuer Import: Groesse beim Allozieren verdoppeln
      69                 :            : 
      70                 :            : 
      71                 :      53302 : void ScColumn::Insert( SCROW nRow, ScBaseCell* pNewCell )
      72                 :            : {
      73                 :      53302 :     sal_Bool bIsAppended = false;
      74         [ +  + ]:      53302 :     if ( !maItems.empty() )
      75                 :            :     {
      76         [ +  + ]:      48954 :         if (maItems.back().nRow < nRow)
      77                 :            :         {
      78                 :      47541 :             Append(nRow, pNewCell );
      79                 :      47541 :             bIsAppended = sal_True;
      80                 :            :         }
      81                 :            :     }
      82         [ +  + ]:      53302 :     if ( !bIsAppended )
      83                 :            :     {
      84                 :            :         SCSIZE  nIndex;
      85 [ +  - ][ +  + ]:       5761 :         if (Search(nRow, nIndex))
      86                 :            :         {
      87                 :        602 :             ScBaseCell* pOldCell = maItems[nIndex].pCell;
      88                 :            : 
      89                 :            :             // move broadcaster and note to new cell, if not existing in new cell
      90 [ +  - ][ +  + ]:        602 :             if (pOldCell->HasBroadcaster() && !pNewCell->HasBroadcaster())
                 [ +  + ]
      91 [ +  - ][ +  - ]:         28 :                 pNewCell->TakeBroadcaster( pOldCell->ReleaseBroadcaster() );
      92                 :            : 
      93 [ +  + ][ +  + ]:        602 :             if ( pOldCell->GetCellType() == CELLTYPE_FORMULA && !pDocument->IsClipOrUndo() )
                 [ +  + ]
      94                 :            :             {
      95         [ +  - ]:         54 :                 pOldCell->EndListeningTo( pDocument );
      96                 :            :                 // falls in EndListening NoteCell in gleicher Col zerstoert
      97 [ +  - ][ -  + ]:         54 :                 if ( nIndex >= maItems.size() || maItems[nIndex].nRow != nRow )
                 [ -  + ]
      98         [ #  # ]:          0 :                     Search(nRow, nIndex);
      99                 :            :             }
     100         [ +  - ]:        602 :             pOldCell->Delete();
     101                 :        602 :             maItems[nIndex].pCell = pNewCell;
     102                 :            :         }
     103                 :            :         else
     104                 :            :         {
     105 [ +  - ][ +  - ]:       5159 :             maItems.insert(maItems.begin() + nIndex, ColEntry());
     106                 :       5159 :             maItems[nIndex].pCell = pNewCell;
     107                 :       5761 :             maItems[nIndex].nRow  = nRow;
     108                 :            :         }
     109                 :            :     }
     110                 :            :     // Bei aus Clipboard sind hier noch falsche (alte) Referenzen!
     111                 :            :     // Werden in CopyBlockFromClip per UpdateReference umgesetzt,
     112                 :            :     // danach StartListeningFromClip und BroadcastFromClip gerufen.
     113                 :            :     // Wird ins Clipboard/UndoDoc gestellt, wird kein Broadcast gebraucht.
     114                 :            :     // Nach Import wird CalcAfterLoad gerufen, dort Listening.
     115 [ +  + ][ +  + ]:      53302 :     if ( !(pDocument->IsClipOrUndo() || pDocument->IsInsertingFromOtherDoc()) )
                 [ +  + ]
     116                 :            :     {
     117                 :      28651 :         pNewCell->StartListeningTo( pDocument );
     118                 :      28651 :         CellType eCellType = pNewCell->GetCellType();
     119                 :            :         // Notizzelle entsteht beim Laden nur durch StartListeningCell,
     120                 :            :         // ausloesende Formelzelle muss sowieso dirty sein.
     121 [ #  # ][ +  - ]:      28651 :         if ( !(pDocument->IsCalcingAfterLoad() && eCellType == CELLTYPE_NOTE) )
                 [ -  + ]
     122                 :            :         {
     123         [ +  + ]:      28651 :             if ( eCellType == CELLTYPE_FORMULA )
     124         [ +  - ]:        647 :                 ((ScFormulaCell*)pNewCell)->SetDirty();
     125                 :            :             else
     126                 :            :                 pDocument->Broadcast( ScHint( SC_HINT_DATACHANGED,
     127 [ +  - ][ +  - ]:      28004 :                     ScAddress( nCol, nRow, nTab ), pNewCell ) );
                 [ +  - ]
     128                 :            :         }
     129                 :            :     }
     130                 :      53302 : }
     131                 :            : 
     132                 :            : 
     133                 :          0 : void ScColumn::Insert( SCROW nRow, sal_uInt32 nNumberFormat, ScBaseCell* pCell )
     134                 :            : {
     135                 :          0 :     Insert(nRow, pCell);
     136                 :            :     short eOldType = pDocument->GetFormatTable()->
     137                 :            :                         GetType( (sal_uLong)
     138                 :          0 :                             ((SfxUInt32Item*)GetAttr( nRow, ATTR_VALUE_FORMAT ))->
     139                 :          0 :                                 GetValue() );
     140                 :          0 :     short eNewType = pDocument->GetFormatTable()->GetType(nNumberFormat);
     141         [ #  # ]:          0 :     if (!pDocument->GetFormatTable()->IsCompatible(eOldType, eNewType))
     142         [ #  # ]:          0 :         ApplyAttr( nRow, SfxUInt32Item( ATTR_VALUE_FORMAT, (sal_uInt32) nNumberFormat) );
     143                 :          0 : }
     144                 :            : 
     145                 :            : 
     146                 :      48561 : void ScColumn::Append( SCROW nRow, ScBaseCell* pCell )
     147                 :            : {
     148         [ +  - ]:      48561 :     maItems.push_back(ColEntry());
     149                 :      48561 :     maItems.back().pCell = pCell;
     150                 :      48561 :     maItems.back().nRow  = nRow;
     151                 :      48561 : }
     152                 :            : 
     153                 :            : 
     154                 :       1030 : void ScColumn::Delete( SCROW nRow )
     155                 :            : {
     156                 :            :     SCSIZE  nIndex;
     157                 :            : 
     158 [ +  - ][ +  + ]:       1030 :     if (Search(nRow, nIndex))
     159                 :            :     {
     160                 :         21 :         ScBaseCell* pCell = maItems[nIndex].pCell;
     161 [ +  - ][ +  - ]:         21 :         ScNoteCell* pNoteCell = new ScNoteCell;
     162                 :         21 :         maItems[nIndex].pCell = pNoteCell;       // Dummy fuer Interpret
     163                 :            :         pDocument->Broadcast( ScHint( SC_HINT_DYING,
     164 [ +  - ][ +  - ]:         21 :             ScAddress( nCol, nRow, nTab ), pCell ) );
                 [ +  - ]
     165 [ +  - ][ -  + ]:         21 :         if ( SvtBroadcaster* pBC = pCell->ReleaseBroadcaster() )
     166                 :            :         {
     167         [ #  # ]:          0 :             pNoteCell->TakeBroadcaster( pBC );
     168                 :            :         }
     169                 :            :         else
     170                 :            :         {
     171         [ +  - ]:         21 :             pNoteCell->Delete();
     172 [ +  - ][ +  - ]:         21 :             maItems.erase( maItems.begin() + nIndex);
     173                 :            :             //  Soll man hier den Speicher freigeben (delta)? Wird dann langsamer!
     174                 :            :         }
     175         [ +  - ]:         21 :         pCell->EndListeningTo( pDocument );
     176         [ +  - ]:         21 :         pCell->Delete();
     177                 :            :     }
     178                 :       1030 : }
     179                 :            : 
     180                 :            : 
     181                 :          3 : void ScColumn::DeleteAtIndex( SCSIZE nIndex )
     182                 :            : {
     183                 :          3 :     ScBaseCell* pCell = maItems[nIndex].pCell;
     184         [ +  - ]:          3 :     ScNoteCell* pNoteCell = new ScNoteCell;
     185                 :          3 :     maItems[nIndex].pCell = pNoteCell;       // Dummy fuer Interpret
     186                 :            :     pDocument->Broadcast( ScHint( SC_HINT_DYING,
     187 [ +  - ][ +  - ]:          3 :         ScAddress( nCol, maItems[nIndex].nRow, nTab ), pCell ) );
                 [ +  - ]
     188                 :          3 :     pNoteCell->Delete();
     189 [ +  - ][ +  - ]:          3 :     maItems.erase(maItems.begin() + nIndex);
     190         [ +  - ]:          3 :     pCell->EndListeningTo( pDocument );
     191                 :          3 :     pCell->Delete();
     192                 :          3 : }
     193                 :            : 
     194                 :            : 
     195                 :    1787904 : void ScColumn::FreeAll()
     196                 :            : {
     197         [ +  + ]:    1836716 :     for (SCSIZE i = 0; i < maItems.size(); i++)
     198                 :      48812 :         maItems[i].pCell->Delete();
     199                 :    1787904 :     maItems.clear();
     200                 :    1787904 : }
     201                 :            : 
     202                 :            : 
     203                 :      10240 : void ScColumn::DeleteRow( SCROW nStartRow, SCSIZE nSize )
     204                 :            : {
     205         [ +  - ]:      10240 :     pAttrArray->DeleteRow( nStartRow, nSize );
     206                 :            : 
     207         [ +  + ]:      10240 :     if ( maItems.empty() )
     208                 :            :         return ;
     209                 :            : 
     210                 :            :     SCSIZE nFirstIndex;
     211         [ +  - ]:          9 :     Search( nStartRow, nFirstIndex );
     212         [ +  + ]:          9 :     if ( nFirstIndex >= maItems.size() )
     213                 :            :         return ;
     214                 :            : 
     215                 :          6 :     sal_Bool bOldAutoCalc = pDocument->GetAutoCalc();
     216         [ +  - ]:          6 :     pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
     217                 :            : 
     218                 :          6 :     sal_Bool bFound=false;
     219                 :          6 :     SCROW nEndRow = nStartRow + nSize - 1;
     220                 :          6 :     SCSIZE nStartIndex = 0;
     221                 :          6 :     SCSIZE nEndIndex = 0;
     222                 :            :     SCSIZE i;
     223                 :            : 
     224 [ +  + ][ +  + ]:         10 :     for ( i = nFirstIndex; i < maItems.size() && maItems[i].nRow <= nEndRow; i++ )
                 [ +  + ]
     225                 :            :     {
     226         [ +  - ]:          4 :         if (!bFound)
     227                 :            :         {
     228                 :          4 :             nStartIndex = i;
     229                 :          4 :             bFound = sal_True;
     230                 :            :         }
     231                 :          4 :         nEndIndex = i;
     232                 :            : 
     233                 :          4 :         ScBaseCell* pCell = maItems[i].pCell;
     234                 :          4 :         SvtBroadcaster* pBC = pCell->GetBroadcaster();
     235         [ -  + ]:          4 :         if (pBC)
     236                 :            :         {
     237                 :            : // gibt jetzt invalid reference, kein Aufruecken der direkten Referenzen
     238                 :            : //          MoveListeners( *pBC, nRow+nSize );
     239         [ #  # ]:          0 :             pCell->DeleteBroadcaster();
     240                 :            :             //  in DeleteRange werden leere Broadcaster geloescht
     241                 :            :         }
     242                 :            :     }
     243         [ +  + ]:          6 :     if (bFound)
     244                 :            :     {
     245         [ +  - ]:          4 :         DeleteRange( nStartIndex, nEndIndex, IDF_CONTENTS );
     246         [ +  - ]:          4 :         Search( nStartRow, i );
     247         [ +  + ]:          4 :         if ( i >= maItems.size() )
     248                 :            :         {
     249         [ +  - ]:          1 :             pDocument->SetAutoCalc( bOldAutoCalc );
     250                 :            :             return ;
     251                 :            :         }
     252                 :            :     }
     253                 :            :     else
     254                 :          2 :         i = nFirstIndex;
     255                 :            : 
     256                 :          5 :     ScAddress aAdr( nCol, 0, nTab );
     257         [ +  - ]:          5 :     ScHint aHint( SC_HINT_DATACHANGED, aAdr, NULL );    // only areas (ScBaseCell* == NULL)
     258                 :          5 :     ScAddress& rAddress = aHint.GetAddress();
     259                 :            :     // for sparse occupation use single broadcasts, not ranges
     260         [ +  - ]:          5 :     bool bSingleBroadcasts = (((maItems.back().nRow - maItems[i].nRow) /
     261                 :          5 :                 (maItems.size() - i)) > 1);
     262         [ -  + ]:          5 :     if ( bSingleBroadcasts )
     263                 :            :     {
     264                 :          0 :         SCROW nLastBroadcast = MAXROW+1;
     265         [ #  # ]:          0 :         for ( ; i < maItems.size(); i++ )
     266                 :            :         {
     267                 :          0 :             SCROW nOldRow = maItems[i].nRow;
     268                 :            :             // Aenderung Quelle broadcasten
     269                 :          0 :             rAddress.SetRow( nOldRow );
     270         [ #  # ]:          0 :             pDocument->AreaBroadcast( aHint );
     271                 :          0 :             SCROW nNewRow = (maItems[i].nRow -= nSize);
     272                 :            :             // Aenderung Ziel broadcasten
     273         [ #  # ]:          0 :             if ( nLastBroadcast != nNewRow )
     274                 :            :             {   // direkt aufeinanderfolgende nicht doppelt broadcasten
     275                 :          0 :                 rAddress.SetRow( nNewRow );
     276         [ #  # ]:          0 :                 pDocument->AreaBroadcast( aHint );
     277                 :            :             }
     278                 :          0 :             nLastBroadcast = nOldRow;
     279                 :          0 :             ScBaseCell* pCell = maItems[i].pCell;
     280         [ #  # ]:          0 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
     281         [ #  # ]:          0 :                 ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
     282                 :            :         }
     283                 :            :     }
     284                 :            :     else
     285                 :            :     {
     286                 :          5 :         rAddress.SetRow( maItems[i].nRow );
     287                 :          5 :         ScRange aRange( rAddress );
     288         [ +  - ]:          5 :         aRange.aEnd.SetRow( maItems.back().nRow );
     289         [ +  + ]:         11 :         for ( ; i < maItems.size(); i++ )
     290                 :            :         {
     291                 :          6 :             SCROW nNewRow = (maItems[i].nRow -= nSize);
     292                 :          6 :             ScBaseCell* pCell = maItems[i].pCell;
     293         [ +  + ]:          6 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
     294         [ +  - ]:          3 :                 ((ScFormulaCell*)pCell)->aPos.SetRow( nNewRow );
     295                 :            :         }
     296         [ +  - ]:          5 :         pDocument->AreaBroadcastInRange( aRange, aHint );
     297                 :            :     }
     298                 :            : 
     299 [ +  - ][ +  - ]:      10240 :     pDocument->SetAutoCalc( bOldAutoCalc );
     300                 :            : }
     301                 :            : 
     302                 :            : 
     303                 :        634 : void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, sal_uInt16 nDelFlag )
     304                 :            : {
     305                 :            :     /*  If caller specifies to not remove the note caption objects, all cells
     306                 :            :         have to forget the pointers to them. This is used e.g. while undoing a
     307                 :            :         "paste cells" operation, which removes the caption objects later in
     308                 :            :         drawing undo. */
     309                 :            : 
     310         [ +  - ]:        634 :     ScHint aHint( SC_HINT_DYING, ScAddress( nCol, 0, nTab ), 0 );
     311                 :            : 
     312                 :            :     // cache all formula cells, they will be deleted at end of this function
     313                 :            :     typedef ::std::vector< ScFormulaCell* > FormulaCellVector;
     314         [ +  - ]:        634 :     FormulaCellVector aDelCells;
     315         [ +  - ]:        634 :     aDelCells.reserve( nEndIndex - nStartIndex + 1 );
     316                 :            : 
     317                 :            :     typedef mdds::flat_segment_tree<SCSIZE, bool> RemovedSegments_t;
     318         [ +  - ]:        634 :     RemovedSegments_t aRemovedSegments(nStartIndex, maItems.size(), false);
     319                 :        634 :     SCSIZE nFirst(nStartIndex);
     320                 :            : 
     321                 :            :     // dummy replacement for old cells, to prevent that interpreter uses old cell
     322 [ +  - ][ +  - ]:        634 :     boost::scoped_ptr<ScNoteCell> pDummyCell(new ScNoteCell);
     323                 :            : 
     324         [ +  + ]:       3938 :     for ( SCSIZE nIdx = nStartIndex; nIdx <= nEndIndex; ++nIdx )
     325                 :            :     {
     326                 :            :         // all content is deleted and cell does not contain broadcaster
     327 [ +  + ][ +  + ]:       3304 :         if (((nDelFlag & IDF_CONTENTS) == IDF_CONTENTS) && !maItems[ nIdx ].pCell->GetBroadcaster())
                 [ +  + ]
     328                 :            :         {
     329                 :       2926 :             ScBaseCell* pOldCell = maItems[ nIdx ].pCell;
     330         [ +  + ]:       2926 :             if (pOldCell->GetCellType() == CELLTYPE_FORMULA)
     331                 :            :             {
     332                 :            :                 // cache formula cell, will be deleted below
     333 [ +  - ][ +  - ]:        234 :                 aDelCells.push_back( static_cast< ScFormulaCell* >( pOldCell ) );
     334                 :            :             }
     335                 :            :             else
     336                 :            :             {
     337                 :            :                 // interpret in broadcast must not use the old cell
     338                 :       2692 :                 maItems[ nIdx ].pCell = pDummyCell.get();
     339                 :       2692 :                 aHint.GetAddress().SetRow( maItems[ nIdx ].nRow );
     340                 :       2692 :                 aHint.SetCell( pOldCell );
     341         [ +  - ]:       2692 :                 pDocument->Broadcast( aHint );
     342         [ +  - ]:       2692 :                 pOldCell->Delete();
     343                 :            :             }
     344                 :            :         }
     345                 :            :         // delete some contents of the cells, or cells with broadcaster
     346                 :            :         else
     347                 :            :         {
     348                 :        378 :             bool bDelete = false;
     349                 :        378 :             ScBaseCell* pOldCell = maItems[nIdx].pCell;
     350                 :        378 :             CellType eCellType = pOldCell->GetCellType();
     351         [ +  + ]:        378 :             if ((nDelFlag & IDF_CONTENTS) == IDF_CONTENTS)
     352                 :        193 :                 bDelete = true;
     353                 :            :             else
     354                 :            :             {
     355                 :            :                 // decide whether to delete the cell object according to passed
     356                 :            :                 // flags
     357   [ +  +  +  -  :        185 :                 switch ( eCellType )
                      - ]
     358                 :            :                 {
     359                 :            :                     case CELLTYPE_VALUE:
     360                 :            :                         {
     361                 :         63 :                             sal_uInt16 nValFlags = nDelFlag & (IDF_DATETIME|IDF_VALUE);
     362                 :            :                             // delete values and dates?
     363                 :         63 :                             bDelete = nValFlags == (IDF_DATETIME|IDF_VALUE);
     364                 :            :                             // if not, decide according to cell number format
     365 [ +  + ][ +  + ]:         63 :                             if( !bDelete && (nValFlags != 0) )
     366                 :            :                             {
     367                 :            :                                 sal_uLong nIndex = (sal_uLong)((SfxUInt32Item*)GetAttr(
     368         [ +  - ]:          8 :                                             maItems[nIdx].nRow, ATTR_VALUE_FORMAT ))->GetValue();
     369 [ +  - ][ +  - ]:          8 :                                 short nType = pDocument->GetFormatTable()->GetType(nIndex);
     370                 :            :                                 bool bIsDate = (nType == NUMBERFORMAT_DATE) ||
     371 [ +  - ][ +  - ]:          8 :                                     (nType == NUMBERFORMAT_TIME) || (nType == NUMBERFORMAT_DATETIME);
                 [ -  + ]
     372         [ -  + ]:          8 :                                 bDelete = nValFlags == (bIsDate ? IDF_DATETIME : IDF_VALUE);
     373                 :            :                             }
     374                 :            :                         }
     375                 :         63 :                         break;
     376                 :            : 
     377                 :            :                     case CELLTYPE_STRING:
     378                 :            :                     case CELLTYPE_EDIT:
     379                 :         81 :                         bDelete = (nDelFlag & IDF_STRING) != 0;
     380                 :         81 :                         break;
     381                 :            : 
     382                 :            :                     case CELLTYPE_FORMULA:
     383                 :         41 :                         bDelete = (nDelFlag & IDF_FORMULA) != 0;
     384                 :         41 :                         break;
     385                 :            : 
     386                 :            :                     case CELLTYPE_NOTE:
     387                 :            :                         // do note delete note cell with broadcaster
     388                 :          0 :                         bDelete = !pOldCell->GetBroadcaster();
     389                 :          0 :                         break;
     390                 :            : 
     391                 :            :                     default:;   // added to avoid warnings
     392                 :            :                 }
     393                 :            :             }
     394                 :            : 
     395         [ +  + ]:        378 :             if (bDelete)
     396                 :            :             {
     397                 :            :                 // try to create a replacement note cell, if note or broadcaster exists
     398                 :        350 :                 ScNoteCell* pNoteCell = NULL;
     399                 :        350 :                 SvtBroadcaster* pBC = pOldCell->GetBroadcaster();
     400 [ +  - ][ +  + ]:        350 :                 bool bKeepBC = pBC && pBC->HasListeners();
     401                 :            :                 // #i99844# do not release broadcaster from old cell, it still has to notify deleted content
     402         [ +  + ]:        350 :                 if ( bKeepBC)
     403 [ +  - ][ +  - ]:        193 :                         pNoteCell = new ScNoteCell( pBC );
     404                 :            : 
     405                 :            :                 // remove cell entry in cell item list
     406                 :        350 :                 SCROW nOldRow = maItems[nIdx].nRow;
     407         [ +  + ]:        350 :                 if (pNoteCell)
     408                 :            :                 {
     409                 :            :                     // replace old cell with the replacement note cell
     410                 :        193 :                     maItems[nIdx].pCell = pNoteCell;
     411                 :            :                     // ... so it's not really deleted
     412                 :        193 :                     bDelete = false;
     413                 :            :                 }
     414                 :            :                 else
     415                 :        157 :                     maItems[nIdx].pCell = pDummyCell.get();
     416                 :            : 
     417                 :            :                 // cache formula cells (will be deleted later), delete cell of other type
     418         [ +  + ]:        350 :                 if (eCellType == CELLTYPE_FORMULA)
     419                 :            :                 {
     420 [ +  - ][ +  - ]:         48 :                     aDelCells.push_back( static_cast< ScFormulaCell* >( pOldCell ) );
     421                 :            :                 }
     422                 :            :                 else
     423                 :            :                 {
     424                 :        302 :                     aHint.GetAddress().SetRow( nOldRow );
     425                 :        302 :                     aHint.SetCell( pOldCell );
     426         [ +  - ]:        302 :                     pDocument->Broadcast( aHint );
     427         [ +  - ]:        302 :                     if (pNoteCell != pOldCell)
     428                 :            :                     {
     429                 :            :                         // #i99844# after broadcasting, old cell has to forget the broadcaster (owned by pNoteCell)
     430         [ +  - ]:        302 :                         pOldCell->ReleaseBroadcaster();
     431         [ +  - ]:        302 :                         pOldCell->Delete();
     432                 :            :                     }
     433                 :            :                 }
     434                 :            :             }
     435                 :            : 
     436         [ +  + ]:        378 :             if (!bDelete)
     437                 :            :             {
     438                 :            :                 // We just came to a non-deleted cell after a segment of
     439                 :            :                 // deleted ones. So we need to remember the segment
     440                 :            :                 // before moving on.
     441         [ +  + ]:        221 :                 if (nFirst < nIdx)
     442         [ +  - ]:         15 :                     aRemovedSegments.insert_back(nFirst, nIdx, true);
     443                 :        221 :                 nFirst = nIdx + 1;
     444                 :            :             }
     445                 :            :         }
     446                 :            :     }
     447                 :            :     // there is a segment of deleted cells at the end
     448         [ +  + ]:        634 :     if (nFirst <= nEndIndex)
     449         [ +  - ]:        597 :         aRemovedSegments.insert_back(nFirst, nEndIndex + 1, true);
     450                 :            : 
     451                 :            :     {
     452         [ +  - ]:        634 :         RemovedSegments_t::const_iterator aIt(aRemovedSegments.begin());
     453         [ +  - ]:        634 :         RemovedSegments_t::const_iterator aEnd(aRemovedSegments.end());
     454                 :            :         // The indexes in aRemovedSegments denote cell positions in the
     455                 :            :         // original array. But as we are shifting it from the left, we have
     456                 :            :         // to compensate for already performed shifts for latter segments.
     457                 :            :         // TODO: use reverse iterators instead
     458                 :        634 :         SCSIZE nShift(0);
     459                 :        634 :         SCSIZE nStartSegment(nStartIndex);
     460                 :        634 :         bool bRemoved = false;
     461 [ +  - ][ +  + ]:       1340 :         while (aIt != aEnd)
     462                 :            :         {
     463 [ +  - ][ +  + ]:        706 :             if (aIt->second)
     464                 :            :             { // this segment removed
     465         [ +  - ]:        612 :                 if (!bRemoved)
     466         [ +  - ]:        612 :                     nStartSegment = aIt->first;
     467                 :            :                     // The first of removes in a row sets start (they should be
     468                 :            :                     // alternating removed/notremoved anyway).
     469                 :        612 :                 bRemoved = true;
     470                 :            :             }
     471                 :            :             else
     472                 :            :             { // this segment not removed
     473         [ +  + ]:         94 :                 if (bRemoved)
     474                 :            :                 { // previous segment(s) removed, move tail
     475         [ +  - ]:         62 :                     SCSIZE const nEndSegment(aIt->first);
     476                 :            :                     memmove(
     477                 :         62 :                             &maItems[nStartSegment - nShift],
     478                 :         62 :                             &maItems[nEndSegment - nShift],
     479                 :         62 :                             (maItems.size() - nEndSegment) * sizeof(ColEntry));
     480                 :         62 :                     nShift += nEndSegment - nStartSegment;
     481                 :         62 :                     bRemoved = false;
     482                 :            :                 }
     483                 :            :             }
     484         [ +  - ]:        706 :             ++aIt;
     485                 :            :         }
     486                 :            :         // The last removed segment up to aItems.size() is discarded, there's
     487                 :            :         // nothing following to be moved.
     488         [ +  + ]:        634 :         if (bRemoved)
     489                 :        550 :             nShift += maItems.size() - nStartSegment;
     490 [ +  - ][ +  - ]:        634 :         maItems.erase(maItems.end() - nShift, maItems.end());
     491                 :            :     }
     492                 :            : 
     493                 :            :     // *** delete all formula cells ***
     494                 :            : 
     495                 :            :     // first, all cells stop listening, may save unneeded recalcualtions
     496 [ +  - ][ +  - ]:        916 :     for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt )
                 [ +  + ]
     497 [ +  - ][ +  - ]:        282 :         (*aIt)->EndListeningTo( pDocument );
     498                 :            : 
     499                 :            :     // #i101869# if the note cell with the broadcaster was deleted in EndListening,
     500                 :            :     // forget the pointer to the broadcaster
     501 [ +  - ][ +  - ]:        916 :     for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt )
                 [ +  + ]
     502                 :            :     {
     503                 :            :         SCSIZE nIndex;
     504 [ +  - ][ +  - ]:        282 :         if ( !Search( (*aIt)->aPos.Row(), nIndex ) )
                 [ +  + ]
     505 [ +  - ][ +  - ]:        275 :             (*aIt)->ReleaseBroadcaster();
     506                 :            :     }
     507                 :            : 
     508                 :            :     // broadcast SC_HINT_DYING for all cells and delete them
     509 [ +  - ][ +  - ]:        916 :     for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt )
                 [ +  + ]
     510                 :            :     {
     511         [ +  - ]:        282 :         aHint.SetAddress( (*aIt)->aPos );
     512 [ +  - ][ +  - ]:        282 :         aHint.SetCell( *aIt );
     513         [ +  - ]:        282 :         pDocument->Broadcast( aHint );
     514                 :            :         // #i99844# after broadcasting, old cell has to forget the broadcaster (owned by replacement note cell)
     515 [ +  - ][ +  - ]:        282 :         (*aIt)->ReleaseBroadcaster();
     516 [ +  - ][ +  - ]:        282 :         (*aIt)->Delete();
     517 [ +  - ][ +  - ]:        634 :     }
                 [ +  - ]
     518                 :        634 : }
     519                 :            : 
     520                 :            : 
     521                 :      12431 : void ScColumn::DeleteArea(SCROW nStartRow, SCROW nEndRow, sal_uInt16 nDelFlag)
     522                 :            : {
     523                 :            :     //  FreeAll darf hier nicht gerufen werden wegen Broadcastern
     524                 :            : 
     525                 :            :     //  Attribute erst am Ende, damit vorher noch zwischen Zahlen und Datum
     526                 :            :     //  unterschieden werden kann (#47901#)
     527                 :            : 
     528                 :      12431 :     sal_uInt16 nContMask = IDF_CONTENTS;
     529                 :            :     //  IDF_NOCAPTIONS needs to be passed too, if IDF_NOTE is set
     530         [ +  + ]:      12431 :     if( nDelFlag & IDF_NOTE )
     531                 :      10167 :         nContMask |= IDF_NOCAPTIONS;
     532                 :      12431 :     sal_uInt16 nContFlag = nDelFlag & nContMask;
     533                 :            : 
     534 [ +  + ][ +  + ]:      12431 :     if ( !maItems.empty() && nContFlag)
                 [ +  + ]
     535                 :            :     {
     536 [ +  + ][ +  + ]:        758 :         if (nStartRow==0 && nEndRow==MAXROW)
     537                 :          3 :             DeleteRange( 0, maItems.size()-1, nContFlag );
     538                 :            :         else
     539                 :            :         {
     540                 :        755 :             sal_Bool bFound=false;
     541                 :        755 :             SCSIZE nStartIndex = 0;
     542                 :        755 :             SCSIZE nEndIndex = 0;
     543         [ +  + ]:       6061 :             for (SCSIZE i = 0; i < maItems.size(); i++)
     544 [ +  + ][ +  + ]:       5306 :                 if ((maItems[i].nRow >= nStartRow) && (maItems[i].nRow <= nEndRow))
                 [ +  + ]
     545                 :            :                 {
     546         [ +  + ]:       3296 :                     if (!bFound)
     547                 :            :                     {
     548                 :        627 :                         nStartIndex = i;
     549                 :        627 :                         bFound = sal_True;
     550                 :            :                     }
     551                 :       3296 :                     nEndIndex = i;
     552                 :            :                 }
     553         [ +  + ]:        755 :             if (bFound)
     554                 :        758 :                 DeleteRange( nStartIndex, nEndIndex, nContFlag );
     555                 :            :         }
     556                 :            :     }
     557                 :            : 
     558         [ -  + ]:      12431 :     if ( nDelFlag & IDF_EDITATTR )
     559                 :            :     {
     560                 :            :         OSL_ENSURE( nContFlag == 0, "DeleteArea: falsche Flags" );
     561                 :          0 :         RemoveEditAttribs( nStartRow, nEndRow );
     562                 :            :     }
     563                 :            : 
     564                 :            :     //  Attribute erst hier
     565         [ +  + ]:      12431 :     if ((nDelFlag & IDF_ATTRIB) == IDF_ATTRIB) pAttrArray->DeleteArea( nStartRow, nEndRow );
     566         [ +  + ]:       7098 :     else if ((nDelFlag & IDF_ATTRIB) != 0) pAttrArray->DeleteHardAttr( nStartRow, nEndRow );
     567                 :      12431 : }
     568                 :            : 
     569                 :            : 
     570                 :          0 : ScFormulaCell* ScColumn::CreateRefCell( ScDocument* pDestDoc, const ScAddress& rDestPos,
     571                 :            :                                             SCSIZE nIndex, sal_uInt16 nFlags ) const
     572                 :            : {
     573                 :          0 :     sal_uInt16 nContFlags = nFlags & IDF_CONTENTS;
     574         [ #  # ]:          0 :     if (!nContFlags)
     575                 :          0 :         return NULL;
     576                 :            : 
     577                 :            :     //  Testen, ob Zelle kopiert werden soll
     578                 :            :     //  auch bei IDF_CONTENTS komplett, wegen Notes / Broadcastern
     579                 :            : 
     580                 :          0 :     sal_Bool bMatch = false;
     581                 :          0 :     ScBaseCell* pCell = maItems[nIndex].pCell;
     582                 :          0 :     CellType eCellType = pCell->GetCellType();
     583   [ #  #  #  # ]:          0 :     switch ( eCellType )
     584                 :            :     {
     585                 :            :         case CELLTYPE_VALUE:
     586                 :            :             {
     587                 :          0 :                 sal_uInt16 nValFlags = nFlags & (IDF_DATETIME|IDF_VALUE);
     588                 :            : 
     589         [ #  # ]:          0 :                 if ( nValFlags == (IDF_DATETIME|IDF_VALUE) )
     590                 :          0 :                     bMatch = sal_True;
     591         [ #  # ]:          0 :                 else if ( nValFlags )
     592                 :            :                 {
     593                 :            :                     sal_uLong nNumIndex = (sal_uLong)((SfxUInt32Item*)GetAttr(
     594         [ #  # ]:          0 :                                     maItems[nIndex].nRow, ATTR_VALUE_FORMAT ))->GetValue();
     595 [ #  # ][ #  # ]:          0 :                     short nTyp = pDocument->GetFormatTable()->GetType(nNumIndex);
     596 [ #  # ][ #  # ]:          0 :                     if ((nTyp == NUMBERFORMAT_DATE) || (nTyp == NUMBERFORMAT_TIME) || (nTyp == NUMBERFORMAT_DATETIME))
                 [ #  # ]
     597                 :          0 :                         bMatch = ((nFlags & IDF_DATETIME) != 0);
     598                 :            :                     else
     599                 :          0 :                         bMatch = ((nFlags & IDF_VALUE) != 0);
     600                 :            :                 }
     601                 :            :             }
     602                 :          0 :             break;
     603                 :            :         case CELLTYPE_STRING:
     604                 :          0 :         case CELLTYPE_EDIT:     bMatch = ((nFlags & IDF_STRING) != 0); break;
     605                 :          0 :         case CELLTYPE_FORMULA:  bMatch = ((nFlags & IDF_FORMULA) != 0); break;
     606                 :            :         default:
     607                 :            :         {
     608                 :            :             // added to avoid warnings
     609                 :            :         }
     610                 :            :     }
     611         [ #  # ]:          0 :     if (!bMatch)
     612                 :          0 :         return NULL;
     613                 :            : 
     614                 :            : 
     615                 :            :     //  Referenz einsetzen
     616                 :            :     ScSingleRefData aRef;
     617                 :          0 :     aRef.nCol = nCol;
     618                 :          0 :     aRef.nRow = maItems[nIndex].nRow;
     619                 :          0 :     aRef.nTab = nTab;
     620                 :          0 :     aRef.InitFlags();                           // -> alles absolut
     621                 :          0 :     aRef.SetFlag3D(true);
     622                 :            : 
     623                 :            :     //! 3D(FALSE) und TabRel(TRUE), wenn die endgueltige Position auf der selben Tabelle ist?
     624                 :            :     //! (bei TransposeClip ist die Zielposition noch nicht bekannt)
     625                 :            : 
     626         [ #  # ]:          0 :     aRef.CalcRelFromAbs( rDestPos );
     627                 :            : 
     628         [ #  # ]:          0 :     ScTokenArray aArr;
     629         [ #  # ]:          0 :     aArr.AddSingleReference( aRef );
     630                 :            : 
     631 [ #  # ][ #  # ]:          0 :     return new ScFormulaCell( pDestDoc, rDestPos, &aArr );
                 [ #  # ]
     632                 :            : }
     633                 :            : 
     634                 :            : 
     635                 :            : //  rColumn = Quelle
     636                 :            : //  nRow1, nRow2 = Zielposition
     637                 :            : 
     638                 :        175 : void ScColumn::CopyFromClip(SCROW nRow1, SCROW nRow2, long nDy,
     639                 :            :                                 sal_uInt16 nInsFlag, bool bAsLink, bool bSkipAttrForEmpty,
     640                 :            :                                 ScColumn& rColumn)
     641                 :            : {
     642         [ +  + ]:        175 :     if ((nInsFlag & IDF_ATTRIB) != 0)
     643                 :            :     {
     644         [ -  + ]:         95 :         if ( bSkipAttrForEmpty )
     645                 :            :         {
     646                 :            :             //  copy only attributes for non-empty cells
     647                 :            :             //  (notes are not counted as non-empty here, to match the content behavior)
     648                 :            : 
     649                 :            :             SCSIZE nStartIndex;
     650         [ #  # ]:          0 :             rColumn.Search( nRow1-nDy, nStartIndex );
     651 [ #  # ][ #  # ]:          0 :             while ( nStartIndex < rColumn.maItems.size() && rColumn.maItems[nStartIndex].nRow <= nRow2-nDy )
                 [ #  # ]
     652                 :            :             {
     653                 :          0 :                 SCSIZE nEndIndex = nStartIndex;
     654         [ #  # ]:          0 :                 if ( rColumn.maItems[nStartIndex].pCell->GetCellType() != CELLTYPE_NOTE )
     655                 :            :                 {
     656                 :          0 :                     SCROW nStartRow = rColumn.maItems[nStartIndex].nRow;
     657                 :          0 :                     SCROW nEndRow = nStartRow;
     658                 :            : 
     659                 :            :                     //  find consecutive non-empty cells
     660                 :            : 
     661   [ #  #  #  #  :          0 :                     while ( nEndRow < nRow2-nDy &&
             #  #  #  # ]
                 [ #  # ]
     662                 :          0 :                             nEndIndex+1 < rColumn.maItems.size() &&
     663                 :          0 :                             rColumn.maItems[nEndIndex+1].nRow == nEndRow+1 &&
     664                 :          0 :                             rColumn.maItems[nEndIndex+1].pCell->GetCellType() != CELLTYPE_NOTE )
     665                 :            :                     {
     666                 :          0 :                         ++nEndIndex;
     667                 :          0 :                         ++nEndRow;
     668                 :            :                     }
     669                 :            : 
     670         [ #  # ]:          0 :                     rColumn.pAttrArray->CopyAreaSafe( nStartRow+nDy, nEndRow+nDy, nDy, *pAttrArray );
     671                 :            :                 }
     672                 :          0 :                 nStartIndex = nEndIndex + 1;
     673                 :            :             }
     674                 :            :         }
     675                 :            :         else
     676                 :         95 :             rColumn.pAttrArray->CopyAreaSafe( nRow1, nRow2, nDy, *pAttrArray );
     677                 :            :     }
     678         [ +  + ]:        175 :     if ((nInsFlag & IDF_CONTENTS) == 0)
     679                 :         80 :         return;
     680                 :            : 
     681 [ -  + ][ #  # ]:         95 :     if ( bAsLink && nInsFlag == IDF_ALL )
     682                 :            :     {
     683                 :            :         //  bei "alles" werden auch leere Zellen referenziert
     684                 :            :         //! IDF_ALL muss immer mehr Flags enthalten, als bei "Inhalte Einfuegen"
     685                 :            :         //! einzeln ausgewaehlt werden koennen!
     686                 :            : 
     687         [ #  # ]:          0 :         Resize( maItems.size() + static_cast<SCSIZE>(nRow2-nRow1+1) );
     688                 :            : 
     689                 :          0 :         ScAddress aDestPos( nCol, 0, nTab );        // Row wird angepasst
     690                 :            : 
     691                 :            :         //  Referenz erzeugen (Quell-Position)
     692                 :            :         ScSingleRefData aRef;
     693                 :          0 :         aRef.nCol = rColumn.nCol;
     694                 :            :         //  nRow wird angepasst
     695                 :          0 :         aRef.nTab = rColumn.nTab;
     696                 :          0 :         aRef.InitFlags();                           // -> alles absolut
     697                 :          0 :         aRef.SetFlag3D(true);
     698                 :            : 
     699         [ #  # ]:          0 :         for (SCROW nDestRow = nRow1; nDestRow <= nRow2; nDestRow++)
     700                 :            :         {
     701                 :          0 :             aRef.nRow = nDestRow - nDy;             // Quell-Zeile
     702                 :          0 :             aDestPos.SetRow( nDestRow );
     703                 :            : 
     704         [ #  # ]:          0 :             aRef.CalcRelFromAbs( aDestPos );
     705         [ #  # ]:          0 :             ScTokenArray aArr;
     706         [ #  # ]:          0 :             aArr.AddSingleReference( aRef );
     707 [ #  # ][ #  # ]:          0 :             Insert( nDestRow, new ScFormulaCell( pDocument, aDestPos, &aArr ) );
         [ #  # ][ #  # ]
     708         [ #  # ]:          0 :         }
     709                 :            : 
     710                 :            :         return;
     711                 :            :     }
     712                 :            : 
     713                 :         95 :     SCSIZE nColCount = rColumn.maItems.size();
     714                 :            : 
     715                 :            :     // ignore IDF_FORMULA - "all contents but no formulas" results in the same number of cells
     716 [ -  + ][ +  + ]:         95 :     if ((nInsFlag & ( IDF_CONTENTS & ~IDF_FORMULA )) == ( IDF_CONTENTS & ~IDF_FORMULA ) && nRow2-nRow1 >= 64)
     717                 :            :     {
     718                 :            :         //! Always do the Resize from the outside, where the number of repetitions is known
     719                 :            :         //! (then it can be removed here)
     720                 :            : 
     721                 :          0 :         SCSIZE nNew = maItems.size() + nColCount;
     722                 :          0 :         Resize( nNew );
     723                 :            :     }
     724                 :            : 
     725                 :         95 :     sal_Bool bAtEnd = false;
     726 [ +  + ][ +  - ]:        397 :     for (SCSIZE i = 0; i < nColCount && !bAtEnd; i++)
                 [ +  + ]
     727                 :            :     {
     728                 :        222 :         SCsROW nDestRow = rColumn.maItems[i].nRow + nDy;
     729         [ -  + ]:        222 :         if ( nDestRow > (SCsROW) nRow2 )
     730                 :          0 :             bAtEnd = sal_True;
     731         [ +  - ]:        222 :         else if ( nDestRow >= (SCsROW) nRow1 )
     732                 :            :         {
     733                 :            :             //  rows at the beginning may be skipped if filtered rows are left out,
     734                 :            :             //  nDestRow may be negative then
     735                 :            : 
     736                 :        222 :             ScAddress aDestPos( nCol, (SCROW)nDestRow, nTab );
     737                 :            : 
     738                 :            :             ScBaseCell* pNewCell = bAsLink ?
     739         [ #  # ]:          0 :                 rColumn.CreateRefCell( pDocument, aDestPos, i, nInsFlag ) :
     740 [ #  # ][ +  - ]:        222 :                 rColumn.CloneCell( i, nInsFlag, *pDocument, aDestPos );
                 [ -  + ]
     741         [ +  - ]:        222 :             if (pNewCell)
     742         [ +  - ]:        222 :                 Insert( aDestPos.Row(), pNewCell );
     743                 :            :         }
     744                 :            :     }
     745                 :            : }
     746                 :            : 
     747                 :            : 
     748                 :            : namespace {
     749                 :            : 
     750                 :            : /** Helper for ScColumn::CloneCell - decides whether to clone a value cell depending on clone flags and number format. */
     751                 :       2089 : bool lclCanCloneValue( ScDocument& rDoc, const ScColumn& rCol, SCROW nRow, bool bCloneValue, bool bCloneDateTime )
     752                 :            : {
     753                 :            :     // values and dates, or nothing to be cloned -> not needed to check number format
     754         [ +  + ]:       2089 :     if( bCloneValue == bCloneDateTime )
     755                 :       2081 :         return bCloneValue;
     756                 :            : 
     757                 :            :     // check number format of value cell
     758                 :          8 :     sal_uLong nNumIndex = (sal_uLong)((SfxUInt32Item*)rCol.GetAttr( nRow, ATTR_VALUE_FORMAT ))->GetValue();
     759                 :          8 :     short nTyp = rDoc.GetFormatTable()->GetType( nNumIndex );
     760 [ +  - ][ -  + ]:          8 :     bool bIsDateTime = (nTyp == NUMBERFORMAT_DATE) || (nTyp == NUMBERFORMAT_TIME) || (nTyp == NUMBERFORMAT_DATETIME);
                 [ +  - ]
     761         [ -  + ]:       2089 :     return bIsDateTime ? bCloneDateTime : bCloneValue;
     762                 :            : }
     763                 :            : 
     764                 :            : } // namespace
     765                 :            : 
     766                 :            : 
     767                 :       3636 : ScBaseCell* ScColumn::CloneCell(SCSIZE nIndex, sal_uInt16 nFlags, ScDocument& rDestDoc, const ScAddress& rDestPos)
     768                 :            : {
     769                 :       3636 :     bool bCloneValue    = (nFlags & IDF_VALUE) != 0;
     770                 :       3636 :     bool bCloneDateTime = (nFlags & IDF_DATETIME) != 0;
     771                 :       3636 :     bool bCloneString   = (nFlags & IDF_STRING) != 0;
     772                 :       3636 :     bool bCloneSpecialBoolean  = (nFlags & IDF_SPECIAL_BOOLEAN) != 0;
     773                 :       3636 :     bool bCloneFormula  = (nFlags & IDF_FORMULA) != 0;
     774                 :       3636 :     bool bForceFormula  = false;
     775                 :            : 
     776                 :       3636 :     ScBaseCell* pNew = 0;
     777                 :       3636 :     ScBaseCell& rSource = *maItems[nIndex].pCell;
     778   [ +  +  +  +  :       3636 :     switch (rSource.GetCellType())
                      - ]
     779                 :            :     {
     780                 :            :         case CELLTYPE_NOTE:
     781                 :            :             // note will be cloned below
     782                 :          4 :         break;
     783                 :            : 
     784                 :            :         case CELLTYPE_STRING:
     785                 :            :         case CELLTYPE_EDIT:
     786                 :            :             // note will be cloned below
     787         [ +  + ]:       1406 :             if (bCloneString)
     788                 :       1345 :                 pNew = rSource.Clone( rDestDoc, rDestPos );
     789                 :       1406 :         break;
     790                 :            : 
     791                 :            :         case CELLTYPE_VALUE:
     792                 :            :             // note will be cloned below
     793         [ +  + ]:       2089 :             if (lclCanCloneValue( *pDocument, *this, maItems[nIndex].nRow, bCloneValue, bCloneDateTime ))
     794                 :       1933 :                 pNew = rSource.Clone( rDestDoc, rDestPos );
     795                 :       2089 :         break;
     796                 :            : 
     797                 :            :         case CELLTYPE_FORMULA:
     798         [ -  + ]:        137 :             if ( bCloneSpecialBoolean )
     799                 :            :             {
     800                 :          0 :                 ScFormulaCell& rForm = (ScFormulaCell&)rSource;
     801                 :          0 :                 rtl::OUStringBuffer aBuf;
     802                 :            :                 // #TODO #FIXME do we have a localisation issue here?
     803         [ #  # ]:          0 :                 rForm.GetFormula( aBuf );
     804         [ #  # ]:          0 :                 rtl::OUString aVal( aBuf.makeStringAndClear() );
     805 [ #  # ][ #  # ]:          0 :                 if ( aVal == "=TRUE()" || aVal == "=FALSE()" )
                 [ #  # ]
     806                 :          0 :                     bForceFormula = true;
     807                 :            :             }
     808 [ +  - ][ +  - ]:        137 :             if (bForceFormula || bCloneFormula)
     809                 :            :             {
     810                 :            :                 // note will be cloned below
     811                 :        137 :                 pNew = rSource.Clone( rDestDoc, rDestPos );
     812                 :            :             }
     813 [ #  # ][ #  # ]:          0 :             else if ( (bCloneValue || bCloneDateTime || bCloneString) && !rDestDoc.IsUndo() )
         [ #  # ][ #  # ]
                 [ #  # ]
     814                 :            :             {
     815                 :            :                 //  ins Undo-Dokument immer nur die Original-Zelle kopieren,
     816                 :            :                 //  aus Formeln keine Value/String-Zellen erzeugen
     817                 :          0 :                 ScFormulaCell& rForm = (ScFormulaCell&)rSource;
     818                 :          0 :                 sal_uInt16 nErr = rForm.GetErrCode();
     819         [ #  # ]:          0 :                 if ( nErr )
     820                 :            :                 {
     821                 :            :                     // error codes are cloned with values
     822         [ #  # ]:          0 :                     if (bCloneValue)
     823                 :            :                     {
     824         [ #  # ]:          0 :                         ScFormulaCell* pErrCell = new ScFormulaCell( &rDestDoc, rDestPos );
     825                 :          0 :                         pErrCell->SetErrCode( nErr );
     826         [ #  # ]:          0 :                         pNew = pErrCell;
     827                 :            :                     }
     828                 :            :                 }
     829         [ #  # ]:          0 :                 else if (rForm.IsValue())
     830                 :            :                 {
     831         [ #  # ]:          0 :                     if (lclCanCloneValue( *pDocument, *this, maItems[nIndex].nRow, bCloneValue, bCloneDateTime ))
     832                 :            :                     {
     833                 :          0 :                         double nVal = rForm.GetValue();
     834         [ #  # ]:          0 :                         pNew = new ScValueCell(nVal);
     835                 :            :                     }
     836                 :            :                 }
     837         [ #  # ]:          0 :                 else if (bCloneString)
     838                 :            :                 {
     839 [ #  # ][ #  # ]:          0 :                     String aString = rForm.GetString();
     840                 :            :                     // do not clone empty string
     841         [ #  # ]:          0 :                     if (aString.Len() > 0)
     842                 :            :                     {
     843 [ #  # ][ #  # ]:          0 :                         if ( rForm.IsMultilineResult() )
     844                 :            :                         {
     845 [ #  # ][ #  # ]:          0 :                             pNew = new ScEditCell( aString, &rDestDoc );
                 [ #  # ]
     846                 :            :                         }
     847                 :            :                         else
     848                 :            :                         {
     849 [ #  # ][ #  # ]:          0 :                             pNew = new ScStringCell( aString );
                 [ #  # ]
     850                 :            :                         }
     851         [ #  # ]:          0 :                     }
     852                 :            :                 }
     853                 :            :             }
     854                 :        137 :         break;
     855                 :            : 
     856                 :            :         default: OSL_FAIL( "ScColumn::CloneCell - unknown cell type" );
     857                 :            :     }
     858                 :            : 
     859                 :       3636 :     return pNew;
     860                 :            : }
     861                 :            : 
     862                 :            : 
     863                 :          0 : void ScColumn::MixMarked( const ScMarkData& rMark, sal_uInt16 nFunction,
     864                 :            :                             bool bSkipEmpty, ScColumn& rSrcCol )
     865                 :            : {
     866                 :            :     SCROW nRow1, nRow2;
     867                 :            : 
     868         [ #  # ]:          0 :     if (rMark.IsMultiMarked())
     869                 :            :     {
     870         [ #  # ]:          0 :         ScMarkArrayIter aIter( rMark.GetArray()+nCol );
     871 [ #  # ][ #  # ]:          0 :         while (aIter.Next( nRow1, nRow2 ))
     872 [ #  # ][ #  # ]:          0 :             MixData( nRow1, nRow2, nFunction, bSkipEmpty, rSrcCol );
     873                 :            :     }
     874                 :          0 : }
     875                 :            : 
     876                 :            : 
     877                 :            : //  Ergebnis in rVal1
     878                 :            : 
     879                 :          0 : sal_Bool lcl_DoFunction( double& rVal1, double nVal2, sal_uInt16 nFunction )
     880                 :            : {
     881                 :          0 :     sal_Bool bOk = false;
     882   [ #  #  #  #  :          0 :     switch (nFunction)
                      # ]
     883                 :            :     {
     884                 :            :         case PASTE_ADD:
     885                 :          0 :             bOk = SubTotal::SafePlus( rVal1, nVal2 );
     886                 :          0 :             break;
     887                 :            :         case PASTE_SUB:
     888                 :          0 :             nVal2 = -nVal2;     //! geht das immer ohne Fehler?
     889                 :          0 :             bOk = SubTotal::SafePlus( rVal1, nVal2 );
     890                 :          0 :             break;
     891                 :            :         case PASTE_MUL:
     892                 :          0 :             bOk = SubTotal::SafeMult( rVal1, nVal2 );
     893                 :          0 :             break;
     894                 :            :         case PASTE_DIV:
     895                 :          0 :             bOk = SubTotal::SafeDiv( rVal1, nVal2 );
     896                 :          0 :             break;
     897                 :            :     }
     898                 :          0 :     return bOk;
     899                 :            : }
     900                 :            : 
     901                 :            : 
     902                 :          0 : void lcl_AddCode( ScTokenArray& rArr, ScFormulaCell* pCell )
     903                 :            : {
     904                 :          0 :     rArr.AddOpCode(ocOpen);
     905                 :            : 
     906                 :          0 :     ScTokenArray* pCode = pCell->GetCode();
     907         [ #  # ]:          0 :     if (pCode)
     908                 :            :     {
     909                 :          0 :         const formula::FormulaToken* pToken = pCode->First();
     910         [ #  # ]:          0 :         while (pToken)
     911                 :            :         {
     912                 :          0 :             rArr.AddToken( *pToken );
     913                 :          0 :             pToken = pCode->Next();
     914                 :            :         }
     915                 :            :     }
     916                 :            : 
     917                 :          0 :     rArr.AddOpCode(ocClose);
     918                 :          0 : }
     919                 :            : 
     920                 :            : 
     921                 :          0 : void ScColumn::MixData( SCROW nRow1, SCROW nRow2,
     922                 :            :                             sal_uInt16 nFunction, bool bSkipEmpty,
     923                 :            :                             ScColumn& rSrcCol )
     924                 :            : {
     925                 :          0 :     SCSIZE nSrcCount = rSrcCol.maItems.size();
     926                 :            : 
     927                 :            :     SCSIZE nIndex;
     928         [ #  # ]:          0 :     Search( nRow1, nIndex );
     929                 :            : 
     930                 :            : //  SCSIZE nSrcIndex = 0;
     931                 :            :     SCSIZE nSrcIndex;
     932         [ #  # ]:          0 :     rSrcCol.Search( nRow1, nSrcIndex );         //! Testen, ob Daten ganz vorne
     933                 :            : 
     934                 :          0 :     SCROW nNextThis = MAXROW+1;
     935         [ #  # ]:          0 :     if ( nIndex < maItems.size() )
     936                 :          0 :         nNextThis = maItems[nIndex].nRow;
     937                 :          0 :     SCROW nNextSrc = MAXROW+1;
     938         [ #  # ]:          0 :     if ( nSrcIndex < nSrcCount )
     939                 :          0 :         nNextSrc = rSrcCol.maItems[nSrcIndex].nRow;
     940                 :            : 
     941 [ #  # ][ #  # ]:          0 :     while ( nNextThis <= nRow2 || nNextSrc <= nRow2 )
                 [ #  # ]
     942                 :            :     {
     943                 :          0 :         SCROW nRow = Min( nNextThis, nNextSrc );
     944                 :            : 
     945                 :          0 :         ScBaseCell* pSrc = NULL;
     946                 :          0 :         ScBaseCell* pDest = NULL;
     947                 :          0 :         ScBaseCell* pNew = NULL;
     948                 :          0 :         sal_Bool bDelete = false;
     949                 :            : 
     950 [ #  # ][ #  # ]:          0 :         if ( nSrcIndex < nSrcCount && nNextSrc == nRow )
     951                 :          0 :             pSrc = rSrcCol.maItems[nSrcIndex].pCell;
     952                 :            : 
     953 [ #  # ][ #  # ]:          0 :         if ( nIndex < maItems.size() && nNextThis == nRow )
                 [ #  # ]
     954                 :          0 :             pDest = maItems[nIndex].pCell;
     955                 :            : 
     956                 :            :         OSL_ENSURE( pSrc || pDest, "Nanu ?" );
     957                 :            : 
     958         [ #  # ]:          0 :         CellType eSrcType  = pSrc  ? pSrc->GetCellType()  : CELLTYPE_NONE;
     959         [ #  # ]:          0 :         CellType eDestType = pDest ? pDest->GetCellType() : CELLTYPE_NONE;
     960                 :            : 
     961 [ #  # ][ #  # ]:          0 :         sal_Bool bSrcEmpty = ( eSrcType == CELLTYPE_NONE || eSrcType == CELLTYPE_NOTE );
     962 [ #  # ][ #  # ]:          0 :         sal_Bool bDestEmpty = ( eDestType == CELLTYPE_NONE || eDestType == CELLTYPE_NOTE );
     963                 :            : 
     964 [ #  # ][ #  # ]:          0 :         if ( bSkipEmpty && bDestEmpty )     // Originalzelle wiederherstellen
     965                 :            :         {
     966         [ #  # ]:          0 :             if ( pSrc )                     // war da eine Zelle?
     967                 :            :             {
     968         [ #  # ]:          0 :                 pNew = pSrc->Clone( *pDocument );
     969                 :            :             }
     970                 :            :         }
     971         [ #  # ]:          0 :         else if ( nFunction )               // wirklich Rechenfunktion angegeben
     972                 :            :         {
     973                 :            :             double nVal1;
     974                 :            :             double nVal2;
     975         [ #  # ]:          0 :             if ( eSrcType == CELLTYPE_VALUE )
     976                 :          0 :                 nVal1 = ((ScValueCell*)pSrc)->GetValue();
     977                 :            :             else
     978                 :          0 :                 nVal1 = 0.0;
     979         [ #  # ]:          0 :             if ( eDestType == CELLTYPE_VALUE )
     980                 :          0 :                 nVal2 = ((ScValueCell*)pDest)->GetValue();
     981                 :            :             else
     982                 :          0 :                 nVal2 = 0.0;
     983                 :            : 
     984                 :            :             //  leere Zellen werden als Werte behandelt
     985                 :            : 
     986 [ #  # ][ #  # ]:          0 :             sal_Bool bSrcVal  = ( bSrcEmpty || eSrcType == CELLTYPE_VALUE );
     987 [ #  # ][ #  # ]:          0 :             sal_Bool bDestVal  = ( bDestEmpty || eDestType == CELLTYPE_VALUE );
     988                 :            : 
     989                 :            :             sal_Bool bSrcText = ( eSrcType == CELLTYPE_STRING ||
     990 [ #  # ][ #  # ]:          0 :                                 eSrcType == CELLTYPE_EDIT );
     991                 :            :             sal_Bool bDestText = ( eDestType == CELLTYPE_STRING ||
     992 [ #  # ][ #  # ]:          0 :                                 eDestType == CELLTYPE_EDIT );
     993                 :            : 
     994                 :            :             //  sonst bleibt nur Formel...
     995                 :            : 
     996 [ #  # ][ #  # ]:          0 :             if ( bSrcEmpty && bDestEmpty )
     997                 :            :             {
     998                 :            :                 //  beide leer -> nix
     999                 :            :             }
    1000 [ #  # ][ #  # ]:          0 :             else if ( bSrcVal && bDestVal )
    1001                 :            :             {
    1002                 :            :                 //  neuen Wert eintragen, oder Fehler bei Ueberlauf
    1003                 :            : 
    1004         [ #  # ]:          0 :                 sal_Bool bOk = lcl_DoFunction( nVal1, nVal2, nFunction );
    1005                 :            : 
    1006         [ #  # ]:          0 :                 if (bOk)
    1007 [ #  # ][ #  # ]:          0 :                     pNew = new ScValueCell( nVal1 );
    1008                 :            :                 else
    1009                 :            :                 {
    1010                 :            :                     ScFormulaCell* pFC = new ScFormulaCell( pDocument,
    1011 [ #  # ][ #  # ]:          0 :                                                 ScAddress( nCol, nRow, nTab ) );
    1012         [ #  # ]:          0 :                     pFC->SetErrCode( errNoValue );
    1013                 :            :                     //! oder NOVALUE, dann auch in consoli,
    1014                 :            :                     //! sonst in Interpreter::GetCellValue die Abfrage auf errNoValue raus
    1015                 :            :                     //! (dann geht Stringzelle+Wertzelle nicht mehr)
    1016         [ #  # ]:          0 :                     pNew = pFC;
    1017                 :          0 :                 }
    1018                 :            :             }
    1019 [ #  # ][ #  # ]:          0 :             else if ( bSrcText || bDestText )
    1020                 :            :             {
    1021                 :            :                 //  mit Texten wird nicht gerechnet - immer "alte" Zelle, also pSrc
    1022                 :            : 
    1023         [ #  # ]:          0 :                 if (pSrc)
    1024         [ #  # ]:          0 :                     pNew = pSrc->Clone( *pDocument );
    1025         [ #  # ]:          0 :                 else if (pDest)
    1026                 :          0 :                     bDelete = sal_True;
    1027                 :            :             }
    1028                 :            :             else
    1029                 :            :             {
    1030                 :            :                 //  Kombination aus Wert und mindestens einer Formel -> Formel erzeugen
    1031                 :            : 
    1032         [ #  # ]:          0 :                 ScTokenArray aArr;
    1033                 :            : 
    1034                 :            :                 //  erste Zelle
    1035         [ #  # ]:          0 :                 if ( eSrcType == CELLTYPE_FORMULA )
    1036 [ #  # ][ #  # ]:          0 :                     lcl_AddCode( aArr, (ScFormulaCell*)pSrc );
    1037                 :            :                 else
    1038         [ #  # ]:          0 :                     aArr.AddDouble( nVal1 );
    1039                 :            : 
    1040                 :            :                 //  Operator
    1041                 :          0 :                 OpCode eOp = ocAdd;
    1042   [ #  #  #  #  :          0 :                 switch ( nFunction )
                      # ]
    1043                 :            :                 {
    1044                 :          0 :                     case PASTE_ADD: eOp = ocAdd; break;
    1045                 :          0 :                     case PASTE_SUB: eOp = ocSub; break;
    1046                 :          0 :                     case PASTE_MUL: eOp = ocMul; break;
    1047                 :          0 :                     case PASTE_DIV: eOp = ocDiv; break;
    1048                 :            :                 }
    1049         [ #  # ]:          0 :                 aArr.AddOpCode(eOp);                // Funktion
    1050                 :            : 
    1051                 :            :                 //  zweite Zelle
    1052         [ #  # ]:          0 :                 if ( eDestType == CELLTYPE_FORMULA )
    1053 [ #  # ][ #  # ]:          0 :                     lcl_AddCode( aArr, (ScFormulaCell*)pDest );
    1054                 :            :                 else
    1055         [ #  # ]:          0 :                     aArr.AddDouble( nVal2 );
    1056                 :            : 
    1057 [ #  # ][ #  # ]:          0 :                 pNew = new ScFormulaCell( pDocument, ScAddress( nCol, nRow, nTab ), &aArr );
         [ #  # ][ #  # ]
    1058                 :            :             }
    1059                 :            :         }
    1060                 :            : 
    1061                 :            : 
    1062 [ #  # ][ #  # ]:          0 :         if ( pNew || bDelete )          // neues Ergebnis ?
    1063                 :            :         {
    1064 [ #  # ][ #  # ]:          0 :             if (pDest && !pNew)                     // alte Zelle da ?
    1065                 :            :             {
    1066         [ #  # ]:          0 :                 if ( pDest->GetBroadcaster() )
    1067 [ #  # ][ #  # ]:          0 :                     pNew = new ScNoteCell;          // Broadcaster uebernehmen
    1068                 :            :                 else
    1069         [ #  # ]:          0 :                     Delete(nRow);                   // -> loeschen
    1070                 :            :             }
    1071         [ #  # ]:          0 :             if (pNew)
    1072         [ #  # ]:          0 :                 Insert(nRow, pNew);     // neue einfuegen
    1073                 :            : 
    1074         [ #  # ]:          0 :             Search( nRow, nIndex );     // alles kann sich verschoben haben
    1075         [ #  # ]:          0 :             if (pNew)
    1076                 :          0 :                 nNextThis = nRow;       // nIndex zeigt jetzt genau auf nRow
    1077                 :            :             else
    1078         [ #  # ]:          0 :                 nNextThis = ( nIndex < maItems.size() ) ? maItems[nIndex].nRow : MAXROW+1;
    1079                 :            :         }
    1080                 :            : 
    1081         [ #  # ]:          0 :         if ( nNextThis == nRow )
    1082                 :            :         {
    1083                 :          0 :             ++nIndex;
    1084         [ #  # ]:          0 :             nNextThis = ( nIndex < maItems.size() ) ? maItems[nIndex].nRow : MAXROW+1;
    1085                 :            :         }
    1086         [ #  # ]:          0 :         if ( nNextSrc == nRow )
    1087                 :            :         {
    1088                 :          0 :             ++nSrcIndex;
    1089                 :            :             nNextSrc = ( nSrcIndex < nSrcCount ) ?
    1090                 :          0 :                             rSrcCol.maItems[nSrcIndex].nRow :
    1091         [ #  # ]:          0 :                             MAXROW+1;
    1092                 :            :         }
    1093                 :            :     }
    1094                 :          0 : }
    1095                 :            : 
    1096                 :            : 
    1097                 :     547967 : ScAttrIterator* ScColumn::CreateAttrIterator( SCROW nStartRow, SCROW nEndRow ) const
    1098                 :            : {
    1099         [ +  - ]:     547967 :     return new ScAttrIterator( pAttrArray, nStartRow, nEndRow );
    1100                 :            : }
    1101                 :            : 
    1102                 :            : 
    1103                 :     406528 : void ScColumn::StartAllListeners()
    1104                 :            : {
    1105         [ +  + ]:     406528 :     if ( !maItems.empty() )
    1106         [ +  + ]:      12527 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1107                 :            :         {
    1108                 :      11755 :             ScBaseCell* pCell = maItems[i].pCell;
    1109         [ +  + ]:      11755 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1110                 :            :             {
    1111                 :         83 :                 SCROW nRow = maItems[i].nRow;
    1112 [ +  - ][ +  - ]:         83 :                 ((ScFormulaCell*)pCell)->StartListeningTo( pDocument );
    1113         [ -  + ]:         83 :                 if ( nRow != maItems[i].nRow )
    1114         [ #  # ]:          0 :                     Search( nRow, i );      // Listener eingefuegt?
    1115                 :            :             }
    1116                 :            :         }
    1117                 :     406528 : }
    1118                 :            : 
    1119                 :            : 
    1120                 :      50176 : void ScColumn::StartNeededListeners()
    1121                 :            : {
    1122         [ +  + ]:      50176 :     if ( !maItems.empty() )
    1123                 :            :     {
    1124         [ +  + ]:        179 :         for (SCSIZE i = 0; i < maItems.size(); i++)
    1125                 :            :         {
    1126                 :        123 :             ScBaseCell* pCell = maItems[i].pCell;
    1127         [ +  + ]:        123 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1128                 :            :             {
    1129         [ +  - ]:         15 :                 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
    1130         [ +  + ]:         15 :                 if (pFCell->NeedsListening())
    1131                 :            :                 {
    1132                 :          2 :                     SCROW nRow = maItems[i].nRow;
    1133         [ +  - ]:          2 :                     pFCell->StartListeningTo( pDocument );
    1134         [ -  + ]:          2 :                     if ( nRow != maItems[i].nRow )
    1135         [ #  # ]:          0 :                         Search( nRow, i );      // Listener eingefuegt?
    1136                 :            :                 }
    1137                 :            :             }
    1138                 :            :         }
    1139                 :            :     }
    1140                 :      50176 : }
    1141                 :            : 
    1142                 :            : 
    1143                 :         95 : void ScColumn::BroadcastInArea( SCROW nRow1, SCROW nRow2 )
    1144                 :            : {
    1145         [ +  - ]:         95 :     if ( !maItems.empty() )
    1146                 :            :     {
    1147                 :            :         SCROW nRow;
    1148                 :            :         SCSIZE nIndex;
    1149         [ +  - ]:         95 :         Search( nRow1, nIndex );
    1150 [ +  + ][ +  - ]:        317 :         while ( nIndex < maItems.size() && (nRow = maItems[nIndex].nRow) <= nRow2 )
                 [ +  + ]
    1151                 :            :         {
    1152                 :        222 :             ScBaseCell* pCell = maItems[nIndex].pCell;
    1153         [ +  + ]:        222 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1154 [ +  - ][ +  - ]:         36 :                 ((ScFormulaCell*)pCell)->SetDirty();
    1155                 :            :             else
    1156                 :            :                 pDocument->Broadcast( ScHint( SC_HINT_DATACHANGED,
    1157 [ +  - ][ +  - ]:        186 :                     ScAddress( nCol, nRow, nTab ), pCell ) );
                 [ +  - ]
    1158                 :        222 :             nIndex++;
    1159                 :            :         }
    1160                 :            :     }
    1161                 :         95 : }
    1162                 :            : 
    1163                 :            : 
    1164                 :         95 : void ScColumn::StartListeningInArea( SCROW nRow1, SCROW nRow2 )
    1165                 :            : {
    1166         [ +  - ]:         95 :     if ( !maItems.empty() )
    1167                 :            :     {
    1168                 :            :         SCROW nRow;
    1169                 :            :         SCSIZE nIndex;
    1170         [ +  - ]:         95 :         Search( nRow1, nIndex );
    1171 [ +  + ][ +  - ]:        317 :         while ( nIndex < maItems.size() && (nRow = maItems[nIndex].nRow) <= nRow2 )
                 [ +  + ]
    1172                 :            :         {
    1173                 :        222 :             ScBaseCell* pCell = maItems[nIndex].pCell;
    1174         [ +  + ]:        222 :             if ( pCell->GetCellType() == CELLTYPE_FORMULA )
    1175 [ +  - ][ +  - ]:         36 :                 ((ScFormulaCell*)pCell)->StartListeningTo( pDocument );
    1176         [ -  + ]:        222 :             if ( nRow != maItems[nIndex].nRow )
    1177         [ #  # ]:          0 :                 Search( nRow, nIndex );     // durch Listening eingefuegt
    1178                 :        222 :             nIndex++;
    1179                 :            :         }
    1180                 :            :     }
    1181                 :         95 : }
    1182                 :            : 
    1183                 :            : 
    1184                 :            : //  TRUE = Zahlformat gesetzt
    1185                 :       4778 : bool ScColumn::SetString( SCROW nRow, SCTAB nTabP, const String& rString,
    1186                 :            :                           formula::FormulaGrammar::AddressConvention eConv,
    1187                 :            :                           ScSetStringParam* pParam )
    1188                 :            : {
    1189                 :       4778 :     bool bNumFmtSet = false;
    1190         [ -  + ]:       4778 :     if (!ValidRow(nRow))
    1191                 :          0 :         return false;
    1192                 :            : 
    1193                 :       4778 :     ScBaseCell* pNewCell = NULL;
    1194                 :       4778 :     sal_Bool bIsLoading = false;
    1195         [ +  + ]:       4778 :     if (rString.Len() > 0)
    1196                 :            :     {
    1197         [ +  - ]:       4717 :         ScSetStringParam aParam;
    1198         [ +  + ]:       4717 :         if (pParam)
    1199                 :       2292 :             aParam = *pParam;
    1200                 :            : 
    1201                 :       4717 :         sal_uInt32 nIndex, nOldIndex = 0;
    1202                 :            :         sal_Unicode cFirstChar;
    1203         [ +  + ]:       4717 :         if (!aParam.mpNumFormatter)
    1204         [ +  - ]:       3886 :             aParam.mpNumFormatter = pDocument->GetFormatTable();
    1205                 :       4717 :         SfxObjectShell* pDocSh = pDocument->GetDocumentShell();
    1206         [ +  + ]:       4717 :         if ( pDocSh )
    1207         [ +  - ]:       4651 :             bIsLoading = pDocSh->IsLoading();
    1208                 :            :         // IsLoading bei ConvertFrom Import
    1209         [ +  + ]:       4717 :         if ( !bIsLoading )
    1210                 :            :         {
    1211         [ +  - ]:       3739 :             nIndex = nOldIndex = GetNumberFormat( nRow );
    1212 [ +  + ][ +  - ]:       6377 :             if ( rString.Len() > 1
                 [ +  + ]
    1213         [ +  - ]:       2638 :                     && aParam.mpNumFormatter->GetType(nIndex) != NUMBERFORMAT_TEXT )
    1214                 :       2638 :                 cFirstChar = rString.GetChar(0);
    1215                 :            :             else
    1216                 :       1101 :                 cFirstChar = 0;                             // Text
    1217                 :            :         }
    1218                 :            :         else
    1219                 :            :         {   // waehrend ConvertFrom Import gibt es keine gesetzten Formate
    1220                 :        978 :             cFirstChar = rString.GetChar(0);
    1221                 :            :         }
    1222                 :            : 
    1223         [ +  + ]:       4717 :         if ( cFirstChar == '=' )
    1224                 :            :         {
    1225         [ -  + ]:        510 :             if ( rString.Len() == 1 )                       // = Text
    1226 [ #  # ][ #  # ]:          0 :                 pNewCell = new ScStringCell( rString );
                 [ #  # ]
    1227                 :            :             else                                            // =Formel
    1228                 :            :                 pNewCell = new ScFormulaCell( pDocument,
    1229                 :            :                     ScAddress( nCol, nRow, nTabP ), rString,
    1230                 :            :                     formula::FormulaGrammar::mergeToGrammar( formula::FormulaGrammar::GRAM_DEFAULT,
    1231 [ +  - ][ +  - ]:        510 :                         eConv), MM_NONE );
         [ +  - ][ +  - ]
    1232                 :            :         }
    1233         [ +  + ]:       4207 :         else if ( cFirstChar == '\'')                       // 'Text
    1234                 :            :         {
    1235                 :         12 :             bool bNumeric = false;
    1236         [ +  - ]:         12 :             if (aParam.mbHandleApostrophe)
    1237                 :            :             {
    1238                 :            :                 // Cell format is not 'Text', and the first char
    1239                 :            :                 // is an apostrophe.  Check if the input is considered a number.
    1240         [ +  - ]:         12 :                 String aTest = rString.Copy(1);
    1241                 :            :                 double fTest;
    1242         [ +  - ]:         12 :                 bNumeric = aParam.mpNumFormatter->IsNumberFormat(aTest, nIndex, fTest);
    1243         [ +  + ]:         12 :                 if (bNumeric)
    1244                 :            :                     // This is a number.  Strip out the first char.
    1245 [ +  - ][ +  - ]:         12 :                     pNewCell = new ScStringCell(aTest);
         [ +  - ][ +  - ]
    1246                 :            :             }
    1247         [ +  + ]:         12 :             if (!bNumeric)
    1248                 :            :                 // This is a normal text. Take it as-is.
    1249 [ +  - ][ +  - ]:          3 :                 pNewCell = new ScStringCell(rString);
                 [ +  - ]
    1250                 :            :         }
    1251                 :            :         else
    1252                 :            :         {
    1253                 :            :             double nVal;
    1254                 :       4195 :             sal_Bool bIsText = false;
    1255         [ +  + ]:       4195 :             if ( bIsLoading )
    1256                 :            :             {
    1257         [ +  + ]:        978 :                 if ( !maItems.empty() )
    1258                 :            :                 {
    1259         [ +  - ]:        819 :                     String aStr;
    1260                 :        819 :                     SCSIZE i = maItems.size();
    1261         [ +  + ]:        819 :                     SCSIZE nStop = (i >= 3 ? i - 3 : 0);
    1262                 :            :                     // die letzten Zellen vergleichen, ob gleicher String
    1263                 :            :                     // und IsNumberFormat eingespart werden kann
    1264 [ +  + ][ +  + ]:       1335 :                     do
         [ +  + ][ +  + ]
    1265                 :            :                     {
    1266                 :       1335 :                         i--;
    1267                 :       1335 :                         ScBaseCell* pCell = maItems[i].pCell;
    1268      [ +  -  + ]:       1335 :                         switch ( pCell->GetCellType() )
    1269                 :            :                         {
    1270                 :            :                             case CELLTYPE_STRING :
    1271         [ +  - ]:        966 :                                 aStr = ((ScStringCell*)pCell)->GetString();
    1272 [ +  - ][ +  + ]:        966 :                                 if ( rString == aStr )
    1273                 :        210 :                                     bIsText = true;
    1274                 :        966 :                             break;
    1275                 :            :                             case CELLTYPE_NOTE :    // durch =Formel referenziert
    1276                 :          0 :                             break;
    1277                 :            :                             default:
    1278         [ +  + ]:        369 :                                 if ( i == maItems.size() - 1 )
    1279                 :        300 :                                     i = 0;
    1280                 :            :                                     // wahrscheinlich ganze Spalte kein String
    1281                 :            :                         }
    1282         [ +  - ]:        819 :                     } while ( i && i > nStop && !bIsText );
    1283                 :            :                 }
    1284                 :            :                 // nIndex fuer IsNumberFormat vorbelegen
    1285         [ +  + ]:        978 :                 if ( !bIsText )
    1286         [ +  - ]:        768 :                     nIndex = nOldIndex = aParam.mpNumFormatter->GetStandardIndex();
    1287                 :            :             }
    1288                 :            : 
    1289                 :            :             do
    1290                 :            :             {
    1291         [ +  + ]:       4195 :                 if (bIsText)
    1292                 :        210 :                     break;
    1293                 :            : 
    1294         [ +  + ]:       3985 :                 if (aParam.mbDetectNumberFormat)
    1295                 :            :                 {
    1296 [ +  - ][ +  + ]:       2445 :                     if (!aParam.mpNumFormatter->IsNumberFormat(rString, nIndex, nVal))
    1297                 :       1057 :                         break;
    1298                 :            : 
    1299         [ +  - ]:       1388 :                     if ( aParam.mpNumFormatter )
    1300                 :            :                     {
    1301                 :            :                         // convert back to the original language if a built-in format was detected
    1302         [ +  - ]:       1388 :                         const SvNumberformat* pOldFormat = aParam.mpNumFormatter->GetEntry( nOldIndex );
    1303         [ +  - ]:       1388 :                         if ( pOldFormat )
    1304         [ +  - ]:       1388 :                             nIndex = aParam.mpNumFormatter->GetFormatForLanguageIfBuiltIn( nIndex, pOldFormat->GetLanguage() );
    1305                 :            :                     }
    1306                 :            : 
    1307 [ +  - ][ +  - ]:       1388 :                     pNewCell = new ScValueCell( nVal );
    1308         [ +  + ]:       1388 :                     if ( nIndex != nOldIndex)
    1309                 :            :                     {
    1310                 :            :                         // #i22345# New behavior: Apply the detected number format only if
    1311                 :            :                         // the old one was the default number, date, time or boolean format.
    1312                 :            :                         // Exception: If the new format is boolean, always apply it.
    1313                 :            : 
    1314                 :        132 :                         sal_Bool bOverwrite = false;
    1315         [ +  - ]:        132 :                         const SvNumberformat* pOldFormat = aParam.mpNumFormatter->GetEntry( nOldIndex );
    1316         [ +  - ]:        132 :                         if ( pOldFormat )
    1317                 :            :                         {
    1318                 :        132 :                             short nOldType = pOldFormat->GetType() & ~NUMBERFORMAT_DEFINED;
    1319 [ #  # ][ #  # ]:        132 :                             if ( nOldType == NUMBERFORMAT_NUMBER || nOldType == NUMBERFORMAT_DATE ||
         [ #  # ][ -  + ]
    1320                 :            :                                  nOldType == NUMBERFORMAT_TIME || nOldType == NUMBERFORMAT_LOGICAL )
    1321                 :            :                             {
    1322         [ +  - ]:        132 :                                 if ( nOldIndex == aParam.mpNumFormatter->GetStandardFormat(
    1323         [ +  - ]:        132 :                                                     nOldType, pOldFormat->GetLanguage() ) )
    1324                 :            :                                 {
    1325                 :        132 :                                     bOverwrite = true;      // default of these types can be overwritten
    1326                 :            :                                 }
    1327                 :            :                             }
    1328                 :            :                         }
    1329 [ -  + ][ #  # ]:        132 :                         if ( !bOverwrite && aParam.mpNumFormatter->GetType( nIndex ) == NUMBERFORMAT_LOGICAL )
         [ #  # ][ -  + ]
    1330                 :            :                         {
    1331                 :          0 :                             bOverwrite = true;              // overwrite anything if boolean was detected
    1332                 :            :                         }
    1333                 :            : 
    1334         [ +  - ]:        132 :                         if ( bOverwrite )
    1335                 :            :                         {
    1336                 :            :                             ApplyAttr( nRow, SfxUInt32Item( ATTR_VALUE_FORMAT,
    1337 [ +  - ][ +  - ]:        132 :                                 (sal_uInt32) nIndex) );
                 [ +  - ]
    1338                 :        132 :                             bNumFmtSet = true;
    1339                 :            :                         }
    1340                 :            :                     }
    1341                 :            :                 }
    1342         [ +  + ]:       1540 :                 else if (aParam.meSetTextNumFormat != ScSetStringParam::Always)
    1343                 :            :                 {
    1344                 :            :                     // Only check if the string is a regular number.
    1345                 :        645 :                     const LocaleDataWrapper* pLocale = aParam.mpNumFormatter->GetLocaleData();
    1346         [ +  - ]:        645 :                     if (!pLocale)
    1347                 :            :                         break;
    1348                 :            : 
    1349         [ +  - ]:        645 :                     LocaleDataItem aLocaleItem = pLocale->getLocaleItem();
    1350                 :        645 :                     const OUString& rDecSep = aLocaleItem.decimalSeparator;
    1351                 :        645 :                     const OUString& rGroupSep = aLocaleItem.thousandSeparator;
    1352 [ +  - ][ -  + ]:        645 :                     if (rDecSep.getLength() != 1 || rGroupSep.getLength() != 1)
                 [ -  + ]
    1353                 :            :                         break;
    1354                 :            : 
    1355                 :        645 :                     sal_Unicode dsep = rDecSep.getStr()[0];
    1356                 :        645 :                     sal_Unicode gsep = rGroupSep.getStr()[0];
    1357                 :            : 
    1358 [ +  - ][ +  + ]:        645 :                     if (!ScStringUtil::parseSimpleNumber(rString, dsep, gsep, nVal))
                 [ +  - ]
    1359                 :            :                         break;
    1360                 :            : 
    1361 [ +  - ][ +  - ]:        645 :                     pNewCell = new ScValueCell(nVal);
                 [ +  + ]
    1362                 :            :                 }
    1363                 :            :             }
    1364                 :            :             while (false);
    1365                 :            : 
    1366         [ +  + ]:       4195 :             if (!pNewCell)
    1367                 :            :             {
    1368 [ +  + ][ +  - ]:       2498 :                 if (aParam.meSetTextNumFormat != ScSetStringParam::Never && aParam.mpNumFormatter->IsNumberFormat(rString, nIndex, nVal))
         [ +  + ][ +  + ]
    1369                 :            :                 {
    1370                 :            :                     // Set the cell format type to Text.
    1371         [ +  - ]:         60 :                     sal_uInt32 nFormat = aParam.mpNumFormatter->GetStandardFormat(NUMBERFORMAT_TEXT);
    1372 [ +  - ][ +  - ]:         60 :                     ScPatternAttr aNewAttrs(pDocument->GetPool());
    1373                 :         60 :                     SfxItemSet& rSet = aNewAttrs.GetItemSet();
    1374 [ +  - ][ +  - ]:         60 :                     rSet.Put( SfxUInt32Item(ATTR_VALUE_FORMAT, nFormat) );
                 [ +  - ]
    1375 [ +  - ][ +  - ]:         60 :                     ApplyPattern(nRow, aNewAttrs);
    1376                 :            :                 }
    1377                 :            : 
    1378 [ +  - ][ +  - ]:       4717 :                 pNewCell = new ScStringCell(rString);
                 [ +  - ]
    1379                 :            :             }
    1380                 :            :         }
    1381                 :            :     }
    1382                 :            : 
    1383 [ +  + ][ +  + ]:       4778 :     if ( bIsLoading && (maItems.empty() || nRow > maItems.back().nRow) )
         [ +  - ][ +  + ]
    1384                 :            :     {   // Search einsparen und ohne Umweg ueber Insert, Listener aufbauen
    1385                 :            :         // und Broadcast kommt eh erst nach dem Laden
    1386         [ +  - ]:        978 :         if ( pNewCell )
    1387                 :        978 :             Append( nRow, pNewCell );
    1388                 :            :     }
    1389                 :            :     else
    1390                 :            :     {
    1391                 :            :         SCSIZE i;
    1392 [ +  - ][ +  + ]:       3800 :         if (Search(nRow, i))
    1393                 :            :         {
    1394                 :        294 :             ScBaseCell* pOldCell = maItems[i].pCell;
    1395         [ +  - ]:        294 :             SvtBroadcaster* pBC = pOldCell->ReleaseBroadcaster();
    1396 [ +  + ][ -  + ]:        294 :             if (pNewCell || pBC)
    1397                 :            :             {
    1398         [ -  + ]:        291 :                 if(!pNewCell)
    1399 [ #  # ][ #  # ]:          0 :                     pNewCell = new ScNoteCell();
    1400                 :            : 
    1401         [ +  + ]:        291 :                 if (pBC)
    1402                 :            :                 {
    1403         [ +  - ]:         91 :                     pNewCell->TakeBroadcaster(pBC);
    1404                 :         91 :                     pLastFormulaTreeTop = 0;    // Err527 Workaround
    1405                 :            :                 }
    1406                 :            : 
    1407         [ +  + ]:        291 :                 if ( pOldCell->GetCellType() == CELLTYPE_FORMULA )
    1408                 :            :                 {
    1409         [ +  - ]:         66 :                     pOldCell->EndListeningTo( pDocument );
    1410                 :            :                     // falls in EndListening NoteCell in gleicher Col zerstoert
    1411 [ +  - ][ -  + ]:         66 :                     if ( i >= maItems.size() || maItems[i].nRow != nRow )
                 [ -  + ]
    1412         [ #  # ]:          0 :                         Search(nRow, i);
    1413                 :            :                 }
    1414         [ +  - ]:        291 :                 pOldCell->Delete();
    1415                 :        291 :                 maItems[i].pCell = pNewCell;         // ersetzen
    1416         [ +  + ]:        582 :                 if ( pNewCell->GetCellType() == CELLTYPE_FORMULA )
    1417                 :            :                 {
    1418         [ +  - ]:         84 :                     pNewCell->StartListeningTo( pDocument );
    1419 [ +  - ][ +  - ]:         84 :                     ((ScFormulaCell*)pNewCell)->SetDirty();
    1420                 :            :                 }
    1421                 :            :                 else
    1422                 :            :                     pDocument->Broadcast( ScHint( SC_HINT_DATACHANGED,
    1423 [ +  - ][ +  - ]:        207 :                         ScAddress( nCol, nRow, nTabP ), pNewCell ) );
                 [ +  - ]
    1424                 :            :             }
    1425                 :            :             else
    1426                 :            :             {
    1427         [ +  - ]:        294 :                 DeleteAtIndex(i);                   // loeschen und Broadcast
    1428                 :            :             }
    1429                 :            :         }
    1430         [ +  + ]:       3506 :         else if (pNewCell)
    1431                 :            :         {
    1432         [ +  - ]:       3800 :             Insert(nRow, pNewCell);                 // neu eintragen und Broadcast
    1433                 :            :         }
    1434                 :            :     }
    1435                 :            : 
    1436                 :            :     //  hier keine Formate mehr fuer Formeln setzen!
    1437                 :            :     //  (werden bei der Ausgabe abgefragt)
    1438                 :            : 
    1439                 :       4778 :     return bNumFmtSet;
    1440                 :            : }
    1441                 :            : 
    1442                 :            : 
    1443                 :          0 : void ScColumn::GetFilterEntries(SCROW nStartRow, SCROW nEndRow, std::vector<ScTypedStrData>& rStrings, bool& rHasDates)
    1444                 :            : {
    1445                 :          0 :     bool bHasDates = false;
    1446         [ #  # ]:          0 :     SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
    1447                 :          0 :     rtl::OUString aString;
    1448                 :            :     SCSIZE nIndex;
    1449                 :            : 
    1450         [ #  # ]:          0 :     Search( nStartRow, nIndex );
    1451                 :            : 
    1452         [ #  # ]:          0 :     for (; nIndex < maItems.size(); ++nIndex)
    1453                 :            :     {
    1454                 :          0 :         SCROW nRow = maItems[nIndex].nRow;
    1455         [ #  # ]:          0 :         if (nRow > nEndRow)
    1456                 :          0 :             break;
    1457                 :            : 
    1458                 :          0 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    1459         [ #  # ]:          0 :         sal_uLong nFormat = GetNumberFormat( nRow );
    1460                 :            : 
    1461         [ #  # ]:          0 :         ScCellFormat::GetInputString( pCell, nFormat, aString, *pFormatter );
    1462                 :            : 
    1463 [ #  # ][ #  # ]:          0 :         if ( pDocument->HasStringData( nCol, nRow, nTab ) )
    1464                 :            :         {
    1465 [ #  # ][ #  # ]:          0 :             rStrings.push_back(ScTypedStrData(aString));
    1466                 :          0 :             continue;
    1467                 :            :         }
    1468                 :            : 
    1469                 :          0 :         double nValue = 0.0;
    1470                 :            : 
    1471      [ #  #  # ]:          0 :         switch ( pCell->GetCellType() )
    1472                 :            :         {
    1473                 :            :             case CELLTYPE_VALUE:
    1474                 :          0 :                 nValue = ((ScValueCell*)pCell)->GetValue();
    1475                 :          0 :                 break;
    1476                 :            : 
    1477                 :            :             case CELLTYPE_FORMULA:
    1478                 :            :             {
    1479         [ #  # ]:          0 :                 ScFormulaCell* pFC = static_cast<ScFormulaCell*>(pCell);
    1480         [ #  # ]:          0 :                 sal_uInt16 nErr = pFC->GetErrCode();
    1481         [ #  # ]:          0 :                 if (nErr)
    1482                 :            :                 {
    1483                 :            :                     // Error cell is evaluated as string (for now).
    1484         [ #  # ]:          0 :                     String aErr = ScGlobal::GetErrorString(nErr);
    1485         [ #  # ]:          0 :                     if (aErr.Len())
    1486                 :            :                     {
    1487 [ #  # ][ #  # ]:          0 :                         rStrings.push_back(ScTypedStrData(aErr));
                 [ #  # ]
    1488                 :          0 :                         continue;
    1489 [ #  # ][ #  # ]:          0 :                     }
    1490                 :            :                 }
    1491                 :            :                 else
    1492         [ #  # ]:          0 :                     nValue = pFC->GetValue();
    1493                 :            :             }
    1494                 :          0 :             break;
    1495                 :            : 
    1496                 :            :             default:
    1497                 :            :                 ;
    1498                 :            :         }
    1499                 :            : 
    1500         [ #  # ]:          0 :         if (pFormatter)
    1501                 :            :         {
    1502         [ #  # ]:          0 :             short nType = pFormatter->GetType(nFormat);
    1503 [ #  # ][ #  # ]:          0 :             if ((nType & NUMBERFORMAT_DATE) && !(nType & NUMBERFORMAT_TIME))
    1504                 :            :             {
    1505                 :            :                 // special case for date values.  Disregard the time
    1506                 :            :                 // element if the number format is of date type.
    1507                 :          0 :                 nValue = ::rtl::math::approxFloor(nValue);
    1508                 :          0 :                 bHasDates = true;
    1509                 :            :             }
    1510                 :            :         }
    1511                 :            : 
    1512 [ #  # ][ #  # ]:          0 :         rStrings.push_back(ScTypedStrData(aString, nValue, ScTypedStrData::Value));
    1513                 :            :     }
    1514                 :            : 
    1515                 :          0 :     rHasDates = bHasDates;
    1516                 :          0 : }
    1517                 :            : 
    1518                 :            : //
    1519                 :            : //  GetDataEntries - Strings aus zusammenhaengendem Bereich um nRow
    1520                 :            : //
    1521                 :            : 
    1522                 :            : //  DATENT_MAX      - max. Anzahl Eintrage in Liste fuer Auto-Eingabe
    1523                 :            : //  DATENT_SEARCH   - max. Anzahl Zellen, die durchsucht werden - neu: nur Strings zaehlen
    1524                 :            : #define DATENT_MAX      200
    1525                 :            : #define DATENT_SEARCH   2000
    1526                 :            : 
    1527                 :            : 
    1528                 :          0 : bool ScColumn::GetDataEntries(SCROW nStartRow, std::set<ScTypedStrData>& rStrings, bool bLimit)
    1529                 :            : {
    1530                 :          0 :     sal_Bool bFound = false;
    1531                 :            :     SCSIZE nThisIndex;
    1532         [ #  # ]:          0 :     sal_Bool bThisUsed = Search( nStartRow, nThisIndex );
    1533         [ #  # ]:          0 :     String aString;
    1534                 :          0 :     sal_uInt16 nCells = 0;
    1535                 :            : 
    1536                 :            :     //  Die Beschraenkung auf angrenzende Zellen (ohne Luecken) ist nicht mehr gewollt
    1537                 :            :     //  (Featurekommission zur 5.1), stattdessen abwechselnd nach oben und unten suchen,
    1538                 :            :     //  damit naheliegende Zellen wenigstens zuerst gefunden werden.
    1539                 :            :     //! Abstaende der Zeilennummern vergleichen? (Performance??)
    1540                 :            : 
    1541                 :          0 :     SCSIZE nUpIndex = nThisIndex;       // zeigt hinter die Zelle
    1542                 :          0 :     SCSIZE nDownIndex = nThisIndex;     // zeigt auf die Zelle
    1543         [ #  # ]:          0 :     if (bThisUsed)
    1544                 :          0 :         ++nDownIndex;                   // Startzelle ueberspringen
    1545                 :            : 
    1546 [ #  # ][ #  # ]:          0 :     while ( nUpIndex || nDownIndex < maItems.size() )
                 [ #  # ]
    1547                 :            :     {
    1548         [ #  # ]:          0 :         if ( nUpIndex )                 // nach oben
    1549                 :            :         {
    1550                 :          0 :             ScBaseCell* pCell = maItems[nUpIndex-1].pCell;
    1551                 :          0 :             CellType eType = pCell->GetCellType();
    1552 [ #  # ][ #  # ]:          0 :             if (eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT)     // nur Strings interessieren
    1553                 :            :             {
    1554         [ #  # ]:          0 :                 if (eType == CELLTYPE_STRING)
    1555         [ #  # ]:          0 :                     aString = ((ScStringCell*)pCell)->GetString();
    1556                 :            :                 else
    1557 [ #  # ][ #  # ]:          0 :                     aString = ((ScEditCell*)pCell)->GetString();
    1558                 :            : 
    1559 [ #  # ][ #  # ]:          0 :                 bool bInserted = rStrings.insert(ScTypedStrData(aString)).second;
                 [ #  # ]
    1560 [ #  # ][ #  # ]:          0 :                 if (bInserted && bLimit && rStrings.size() >= DATENT_MAX)
         [ #  # ][ #  # ]
    1561                 :          0 :                     break;                                                  // Maximum erreicht
    1562                 :          0 :                 bFound = true;
    1563                 :            : 
    1564         [ #  # ]:          0 :                 if ( bLimit )
    1565         [ #  # ]:          0 :                     if (++nCells >= DATENT_SEARCH)
    1566                 :          0 :                         break;                                  // genug gesucht
    1567                 :            :             }
    1568                 :          0 :             --nUpIndex;
    1569                 :            :         }
    1570                 :            : 
    1571         [ #  # ]:          0 :         if ( nDownIndex < maItems.size() )      // nach unten
    1572                 :            :         {
    1573                 :          0 :             ScBaseCell* pCell = maItems[nDownIndex].pCell;
    1574                 :          0 :             CellType eType = pCell->GetCellType();
    1575 [ #  # ][ #  # ]:          0 :             if (eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT)     // nur Strings interessieren
    1576                 :            :             {
    1577         [ #  # ]:          0 :                 if (eType == CELLTYPE_STRING)
    1578         [ #  # ]:          0 :                     aString = ((ScStringCell*)pCell)->GetString();
    1579                 :            :                 else
    1580 [ #  # ][ #  # ]:          0 :                     aString = ((ScEditCell*)pCell)->GetString();
    1581                 :            : 
    1582 [ #  # ][ #  # ]:          0 :                 bool bInserted = rStrings.insert(ScTypedStrData(aString)).second;
                 [ #  # ]
    1583 [ #  # ][ #  # ]:          0 :                 if (bInserted && bLimit && rStrings.size() >= DATENT_MAX)
         [ #  # ][ #  # ]
    1584                 :          0 :                     break;                                                  // Maximum erreicht
    1585                 :          0 :                 bFound = true;
    1586                 :            : 
    1587         [ #  # ]:          0 :                 if ( bLimit )
    1588         [ #  # ]:          0 :                     if (++nCells >= DATENT_SEARCH)
    1589                 :          0 :                         break;                                  // genug gesucht
    1590                 :            :             }
    1591                 :          0 :             ++nDownIndex;
    1592                 :            :         }
    1593                 :            :     }
    1594                 :            : 
    1595         [ #  # ]:          0 :     return bFound;
    1596                 :            : }
    1597                 :            : 
    1598                 :            : #undef DATENT_MAX
    1599                 :            : #undef DATENT_SEARCH
    1600                 :            : 
    1601                 :            : 
    1602                 :          0 : void ScColumn::RemoveProtected( SCROW nStartRow, SCROW nEndRow )
    1603                 :            : {
    1604         [ #  # ]:          0 :     ScAttrIterator aAttrIter( pAttrArray, nStartRow, nEndRow );
    1605                 :          0 :     SCROW nTop = -1;
    1606                 :          0 :     SCROW nBottom = -1;
    1607                 :            :     SCSIZE nIndex;
    1608         [ #  # ]:          0 :     const ScPatternAttr* pPattern = aAttrIter.Next( nTop, nBottom );
    1609         [ #  # ]:          0 :     while (pPattern)
    1610                 :            :     {
    1611         [ #  # ]:          0 :         const ScProtectionAttr* pAttr = (const ScProtectionAttr*)&pPattern->GetItem(ATTR_PROTECTION);
    1612         [ #  # ]:          0 :         if ( pAttr->GetHideCell() )
    1613         [ #  # ]:          0 :             DeleteArea( nTop, nBottom, IDF_CONTENTS );
    1614         [ #  # ]:          0 :         else if ( pAttr->GetHideFormula() )
    1615                 :            :         {
    1616         [ #  # ]:          0 :             Search( nTop, nIndex );
    1617 [ #  # ][ #  # ]:          0 :             while ( nIndex<maItems.size() && maItems[nIndex].nRow<=nBottom )
                 [ #  # ]
    1618                 :            :             {
    1619         [ #  # ]:          0 :                 if ( maItems[nIndex].pCell->GetCellType() == CELLTYPE_FORMULA )
    1620                 :            :                 {
    1621         [ #  # ]:          0 :                     ScFormulaCell* pFormula = (ScFormulaCell*)maItems[nIndex].pCell;
    1622 [ #  # ][ #  # ]:          0 :                     if (pFormula->IsValue())
    1623                 :            :                     {
    1624         [ #  # ]:          0 :                         double nVal = pFormula->GetValue();
    1625 [ #  # ][ #  # ]:          0 :                         maItems[nIndex].pCell = new ScValueCell( nVal );
    1626                 :            :                     }
    1627                 :            :                     else
    1628                 :            :                     {
    1629 [ #  # ][ #  # ]:          0 :                         String aString = pFormula->GetString();
    1630 [ #  # ][ #  # ]:          0 :                         maItems[nIndex].pCell = new ScStringCell( aString );
         [ #  # ][ #  # ]
    1631                 :            :                     }
    1632 [ #  # ][ #  # ]:          0 :                     delete pFormula;
    1633                 :            :                 }
    1634                 :          0 :                 ++nIndex;
    1635                 :            :             }
    1636                 :            :         }
    1637                 :            : 
    1638         [ #  # ]:          0 :         pPattern = aAttrIter.Next( nTop, nBottom );
    1639                 :            :     }
    1640                 :          0 : }
    1641                 :            : 
    1642                 :            : 
    1643                 :         37 : void ScColumn::SetError( SCROW nRow, const sal_uInt16 nError)
    1644                 :            : {
    1645         [ +  - ]:         37 :     if (VALIDROW(nRow))
    1646                 :            :     {
    1647                 :            :         ScFormulaCell* pCell = new ScFormulaCell
    1648 [ +  - ][ +  - ]:         37 :             ( pDocument, ScAddress( nCol, nRow, nTab ) );
    1649                 :         37 :         pCell->SetErrCode( nError );
    1650         [ +  - ]:         37 :         Insert( nRow, pCell );
    1651                 :            :     }
    1652                 :         37 : }
    1653                 :            : 
    1654                 :            : 
    1655                 :      26076 : void ScColumn::SetValue( SCROW nRow, const double& rVal)
    1656                 :            : {
    1657         [ +  - ]:      26076 :     if (VALIDROW(nRow))
    1658                 :            :     {
    1659         [ +  - ]:      26076 :         ScBaseCell* pCell = new ScValueCell(rVal);
    1660                 :      26076 :         Insert( nRow, pCell );
    1661                 :            :     }
    1662                 :      26076 : }
    1663                 :            : 
    1664                 :            : 
    1665                 :      17785 : void ScColumn::GetString( SCROW nRow, rtl::OUString& rString ) const
    1666                 :            : {
    1667                 :            :     SCSIZE  nIndex;
    1668                 :            :     Color* pColor;
    1669 [ +  - ][ +  + ]:      17785 :     if (Search(nRow, nIndex))
    1670                 :            :     {
    1671                 :      10629 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    1672         [ +  - ]:      10629 :         if (pCell->GetCellType() != CELLTYPE_NOTE)
    1673                 :            :         {
    1674         [ +  - ]:      10629 :             sal_uLong nFormat = GetNumberFormat( nRow );
    1675 [ +  - ][ +  - ]:      10629 :             ScCellFormat::GetString( pCell, nFormat, rString, &pColor, *(pDocument->GetFormatTable()) );
    1676                 :            :         }
    1677                 :            :         else
    1678                 :          0 :             rString = rtl::OUString();
    1679                 :            :     }
    1680                 :            :     else
    1681                 :       7156 :         rString = rtl::OUString();
    1682                 :      17785 : }
    1683                 :            : 
    1684                 :            : 
    1685                 :       2022 : void ScColumn::GetInputString( SCROW nRow, rtl::OUString& rString ) const
    1686                 :            : {
    1687                 :            :     SCSIZE  nIndex;
    1688 [ +  - ][ +  + ]:       2022 :     if (Search(nRow, nIndex))
    1689                 :            :     {
    1690                 :        655 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    1691         [ +  + ]:        655 :         if (pCell->GetCellType() != CELLTYPE_NOTE)
    1692                 :            :         {
    1693         [ +  - ]:        653 :             sal_uLong nFormat = GetNumberFormat( nRow );
    1694 [ +  - ][ +  - ]:        653 :             ScCellFormat::GetInputString( pCell, nFormat, rString, *(pDocument->GetFormatTable()) );
    1695                 :            :         }
    1696                 :            :         else
    1697                 :          2 :             rString = rtl::OUString();
    1698                 :            :     }
    1699                 :            :     else
    1700                 :       1367 :         rString = rtl::OUString();
    1701                 :       2022 : }
    1702                 :            : 
    1703                 :            : 
    1704                 :       3246 : double ScColumn::GetValue( SCROW nRow ) const
    1705                 :            : {
    1706                 :            :     SCSIZE  nIndex;
    1707 [ +  - ][ +  + ]:       3246 :     if (Search(nRow, nIndex))
    1708                 :            :     {
    1709                 :       2577 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    1710      [ +  +  + ]:       2577 :         switch (pCell->GetCellType())
    1711                 :            :         {
    1712                 :            :             case CELLTYPE_VALUE:
    1713                 :       1703 :                 return ((ScValueCell*)pCell)->GetValue();
    1714                 :            : //                break;
    1715                 :            :             case CELLTYPE_FORMULA:
    1716                 :            :                 {
    1717 [ +  - ][ +  - ]:        870 :                     if (((ScFormulaCell*)pCell)->IsValue())
                 [ +  + ]
    1718 [ +  - ][ +  - ]:        867 :                         return ((ScFormulaCell*)pCell)->GetValue();
    1719                 :            :                     else
    1720                 :          3 :                         return 0.0;
    1721                 :            :                 }
    1722                 :            : //                break;
    1723                 :            :             default:
    1724                 :          4 :                 return 0.0;
    1725                 :            : //                break;
    1726                 :            :         }
    1727                 :            :     }
    1728                 :       3246 :     return 0.0;
    1729                 :            : }
    1730                 :            : 
    1731                 :            : 
    1732                 :         42 : void ScColumn::GetFormula( SCROW nRow, rtl::OUString& rFormula ) const
    1733                 :            : {
    1734                 :            :     SCSIZE  nIndex;
    1735 [ +  - ][ +  - ]:         42 :     if (Search(nRow, nIndex))
    1736                 :            :     {
    1737                 :         42 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    1738         [ +  - ]:         42 :         if (pCell->GetCellType() == CELLTYPE_FORMULA)
    1739 [ +  - ][ +  - ]:         42 :             ((ScFormulaCell*)pCell)->GetFormula( rFormula );
    1740                 :            :         else
    1741                 :          0 :             rFormula = rtl::OUString();
    1742                 :            :     }
    1743                 :            :     else
    1744                 :          0 :         rFormula = rtl::OUString();
    1745                 :         42 : }
    1746                 :            : 
    1747                 :            : 
    1748                 :       1812 : CellType ScColumn::GetCellType( SCROW nRow ) const
    1749                 :            : {
    1750                 :            :     SCSIZE  nIndex;
    1751 [ +  - ][ +  + ]:       1812 :     if (Search(nRow, nIndex))
    1752                 :        550 :         return maItems[nIndex].pCell->GetCellType();
    1753                 :       1812 :     return CELLTYPE_NONE;
    1754                 :            : }
    1755                 :            : 
    1756                 :    1998173 : SCSIZE ScColumn::GetCellCount() const
    1757                 :            : {
    1758                 :    1998173 :     return maItems.size();
    1759                 :            : }
    1760                 :            : 
    1761                 :       1657 : sal_uInt16 ScColumn::GetErrCode( SCROW nRow ) const
    1762                 :            : {
    1763                 :            :     SCSIZE  nIndex;
    1764 [ +  - ][ +  + ]:       1657 :     if (Search(nRow, nIndex))
    1765                 :            :     {
    1766                 :       1537 :         ScBaseCell* pCell = maItems[nIndex].pCell;
    1767         [ -  + ]:       1537 :         if (pCell->GetCellType() == CELLTYPE_FORMULA)
    1768 [ #  # ][ #  # ]:          0 :             return ((ScFormulaCell*)pCell)->GetErrCode();
    1769                 :            :     }
    1770                 :       1657 :     return 0;
    1771                 :            : }
    1772                 :            : 
    1773                 :            : 
    1774                 :         15 : bool ScColumn::HasStringData( SCROW nRow ) const
    1775                 :            : {
    1776                 :            :     SCSIZE  nIndex;
    1777 [ +  - ][ +  + ]:         15 :     if (Search(nRow, nIndex))
    1778         [ +  - ]:         12 :         return (maItems[nIndex].pCell)->HasStringData();
    1779                 :         15 :     return false;
    1780                 :            : }
    1781                 :            : 
    1782                 :            : 
    1783                 :       2150 : bool ScColumn::HasValueData( SCROW nRow ) const
    1784                 :            : {
    1785                 :            :     SCSIZE  nIndex;
    1786 [ +  - ][ +  + ]:       2150 :     if (Search(nRow, nIndex))
    1787         [ +  - ]:       1879 :         return (maItems[nIndex].pCell)->HasValueData();
    1788                 :       2150 :     return false;
    1789                 :            : }
    1790                 :            : 
    1791                 :          0 : bool ScColumn::HasStringCells( SCROW nStartRow, SCROW nEndRow ) const
    1792                 :            : {
    1793                 :            :     //  TRUE, wenn String- oder Editzellen im Bereich
    1794                 :            : 
    1795         [ #  # ]:          0 :     if ( !maItems.empty() )
    1796                 :            :     {
    1797                 :            :         SCSIZE nIndex;
    1798         [ #  # ]:          0 :         Search( nStartRow, nIndex );
    1799 [ #  # ][ #  # ]:          0 :         while ( nIndex < maItems.size() && maItems[nIndex].nRow <= nEndRow )
                 [ #  # ]
    1800                 :            :         {
    1801                 :          0 :             CellType eType = maItems[nIndex].pCell->GetCellType();
    1802 [ #  # ][ #  # ]:          0 :             if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT )
    1803                 :          0 :                 return sal_True;
    1804                 :          0 :             ++nIndex;
    1805                 :            :         }
    1806                 :            :     }
    1807                 :          0 :     return false;
    1808                 :            : }
    1809                 :            : 
    1810                 :            : 
    1811                 :          0 : sal_Int32 ScColumn::GetMaxStringLen( SCROW nRowStart, SCROW nRowEnd, CharSet eCharSet ) const
    1812                 :            : {
    1813                 :          0 :     sal_Int32 nStringLen = 0;
    1814         [ #  # ]:          0 :     if ( !maItems.empty() )
    1815                 :            :     {
    1816                 :          0 :         rtl::OUString aString;
    1817                 :          0 :         rtl::OString aOString;
    1818         [ #  # ]:          0 :         bool bIsOctetTextEncoding = rtl_isOctetTextEncoding( eCharSet);
    1819         [ #  # ]:          0 :         SvNumberFormatter* pNumFmt = pDocument->GetFormatTable();
    1820                 :            :         SCSIZE nIndex;
    1821                 :            :         SCROW nRow;
    1822         [ #  # ]:          0 :         Search( nRowStart, nIndex );
    1823 [ #  # ][ #  # ]:          0 :         while ( nIndex < maItems.size() && (nRow = maItems[nIndex].nRow) <= nRowEnd )
                 [ #  # ]
    1824                 :            :         {
    1825                 :          0 :             ScBaseCell* pCell = maItems[nIndex].pCell;
    1826         [ #  # ]:          0 :             if ( pCell->GetCellType() != CELLTYPE_NOTE )
    1827                 :            :             {
    1828                 :            :                 Color* pColor;
    1829                 :            :                 sal_uLong nFormat = (sal_uLong) ((SfxUInt32Item*) GetAttr(
    1830         [ #  # ]:          0 :                     nRow, ATTR_VALUE_FORMAT ))->GetValue();
    1831                 :            :                 ScCellFormat::GetString( pCell, nFormat, aString, &pColor,
    1832         [ #  # ]:          0 :                     *pNumFmt );
    1833                 :            :                 sal_Int32 nLen;
    1834         [ #  # ]:          0 :                 if (bIsOctetTextEncoding)
    1835                 :            :                 {
    1836                 :          0 :                     if (!aString.convertToString( &aOString, eCharSet,
    1837                 :            :                                 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
    1838                 :          0 :                                 RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
    1839                 :            :                     {
    1840                 :            :                         // TODO: anything? this is used by the dBase export filter
    1841                 :            :                         // that throws an error anyway, but in case of another
    1842                 :            :                         // context we might want to indicate a conversion error
    1843                 :            :                         // early.
    1844                 :            :                     }
    1845                 :          0 :                     nLen = aOString.getLength();
    1846                 :            :                 }
    1847                 :            :                 else
    1848                 :          0 :                     nLen = aString.getLength() * sizeof(sal_Unicode);
    1849         [ #  # ]:          0 :                 if ( nStringLen < nLen)
    1850                 :          0 :                     nStringLen = nLen;
    1851                 :            :             }
    1852                 :          0 :             nIndex++;
    1853                 :          0 :         }
    1854                 :            :     }
    1855                 :          0 :     return nStringLen;
    1856                 :            : }
    1857                 :            : 
    1858                 :            : 
    1859                 :          0 : xub_StrLen ScColumn::GetMaxNumberStringLen(
    1860                 :            :     sal_uInt16& nPrecision, SCROW nRowStart, SCROW nRowEnd ) const
    1861                 :            : {
    1862                 :          0 :     xub_StrLen nStringLen = 0;
    1863                 :          0 :     nPrecision = pDocument->GetDocOptions().GetStdPrecision();
    1864         [ #  # ]:          0 :     if ( nPrecision == SvNumberFormatter::UNLIMITED_PRECISION )
    1865                 :            :         // In case of unlimited precision, use 2 instead.
    1866                 :          0 :         nPrecision = 2;
    1867                 :            : 
    1868         [ #  # ]:          0 :     if ( !maItems.empty() )
    1869                 :            :     {
    1870                 :          0 :         rtl::OUString aString;
    1871         [ #  # ]:          0 :         SvNumberFormatter* pNumFmt = pDocument->GetFormatTable();
    1872                 :            :         SCSIZE nIndex;
    1873                 :            :         SCROW nRow;
    1874         [ #  # ]:          0 :         Search( nRowStart, nIndex );
    1875 [ #  # ][ #  # ]:          0 :         while ( nIndex < maItems.size() && (nRow = maItems[nIndex].nRow) <= nRowEnd )
                 [ #  # ]
    1876                 :            :         {
    1877                 :          0 :             ScBaseCell* pCell = maItems[nIndex].pCell;
    1878                 :          0 :             CellType eType = pCell->GetCellType();
    1879 [ #  # ][ #  # ]:          0 :             if ( eType == CELLTYPE_VALUE || (eType == CELLTYPE_FORMULA
         [ #  # ][ #  # ]
    1880 [ #  # ][ #  # ]:          0 :                     && ((ScFormulaCell*)pCell)->IsValue()) )
    1881                 :            :             {
    1882                 :            :                 sal_uLong nFormat = (sal_uLong) ((SfxUInt32Item*) GetAttr(
    1883         [ #  # ]:          0 :                     nRow, ATTR_VALUE_FORMAT ))->GetValue();
    1884         [ #  # ]:          0 :                 ScCellFormat::GetInputString( pCell, nFormat, aString, *pNumFmt );
    1885                 :          0 :                 xub_StrLen nLen = aString.getLength();
    1886         [ #  # ]:          0 :                 if ( nLen )
    1887                 :            :                 {
    1888         [ #  # ]:          0 :                     if ( nFormat )
    1889                 :            :                     {
    1890         [ #  # ]:          0 :                         const SvNumberformat* pEntry = pNumFmt->GetEntry( nFormat );
    1891                 :            :                         sal_uInt16 nPrec;
    1892         [ #  # ]:          0 :                         if (pEntry)
    1893                 :            :                         {
    1894                 :            :                             bool bThousand, bNegRed;
    1895                 :            :                             sal_uInt16 nLeading;
    1896         [ #  # ]:          0 :                             pEntry->GetFormatSpecialInfo(bThousand, bNegRed, nPrec, nLeading);
    1897                 :            :                         }
    1898                 :            :                         else
    1899         [ #  # ]:          0 :                             nPrec = pNumFmt->GetFormatPrecision( nFormat );
    1900                 :            : 
    1901 [ #  # ][ #  # ]:          0 :                         if ( nPrec != SvNumberFormatter::UNLIMITED_PRECISION && nPrec > nPrecision )
    1902                 :          0 :                             nPrecision = nPrec;
    1903                 :            :                     }
    1904         [ #  # ]:          0 :                     if ( nPrecision )
    1905                 :            :                     {   // less than nPrecision in string => widen it
    1906                 :            :                         // more => shorten it
    1907         [ #  # ]:          0 :                         String aSep = pNumFmt->GetFormatDecimalSep( nFormat );
    1908         [ #  # ]:          0 :                         sal_Int32 nTmp = aString.indexOf( aSep );
    1909         [ #  # ]:          0 :                         if ( nTmp == -1 )
    1910                 :          0 :                             nLen += nPrecision + aSep.Len();
    1911                 :            :                         else
    1912                 :            :                         {
    1913                 :          0 :                             nTmp = aString.getLength() - (nTmp + aSep.Len());
    1914         [ #  # ]:          0 :                             if ( nTmp != nPrecision )
    1915                 :          0 :                                 nLen += nPrecision - nTmp;
    1916                 :            :                                 // nPrecision > nTmp : nLen + Diff
    1917                 :            :                                 // nPrecision < nTmp : nLen - Diff
    1918         [ #  # ]:          0 :                         }
    1919                 :            :                     }
    1920         [ #  # ]:          0 :                     if ( nStringLen < nLen )
    1921                 :          0 :                         nStringLen = nLen;
    1922                 :            :                 }
    1923                 :            :             }
    1924                 :          0 :             nIndex++;
    1925                 :          0 :         }
    1926                 :            :     }
    1927                 :          0 :     return nStringLen;
    1928 [ +  - ][ +  - ]:        153 : }
    1929                 :            : 
    1930                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10