LCOV - code coverage report
Current view: top level - sc/source/core/data - attarray.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 797 1138 70.0 %
Date: 2012-08-25 Functions: 42 52 80.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 712 1470 48.4 %

           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 "scitems.hxx"
      30                 :            : #include <svx/algitem.hxx>
      31                 :            : #include <editeng/boxitem.hxx>
      32                 :            : #include <editeng/bolnitem.hxx>
      33                 :            : #include <editeng/frmdiritem.hxx>
      34                 :            : #include <editeng/shaditem.hxx>
      35                 :            : #include <editeng/editobj.hxx>
      36                 :            : #include <editeng/justifyitem.hxx>
      37                 :            : #include <svl/poolcach.hxx>
      38                 :            : #include <editeng/fontitem.hxx>
      39                 :            : #include <unotools/fontcvt.hxx>
      40                 :            : 
      41                 :            : #include "attarray.hxx"
      42                 :            : #include "global.hxx"
      43                 :            : #include "document.hxx"
      44                 :            : #include "docpool.hxx"
      45                 :            : #include "patattr.hxx"
      46                 :            : #include "stlsheet.hxx"
      47                 :            : #include "stlpool.hxx"
      48                 :            : #include "markarr.hxx"
      49                 :            : #include "rechead.hxx"
      50                 :            : #include "globstr.hrc"
      51                 :            : #include "segmenttree.hxx"
      52                 :            : #include "cell.hxx"
      53                 :            : #include <rtl/strbuf.hxx>
      54                 :            : 
      55                 :            : // STATIC DATA -----------------------------------------------------------
      56                 :            : 
      57                 :            : //------------------------------------------------------------------------
      58                 :            : using ::editeng::SvxBorderLine;
      59                 :            : 
      60                 :    1982464 : ScAttrArray::ScAttrArray( SCCOL nNewCol, SCTAB nNewTab, ScDocument* pDoc ) :
      61                 :            :     nCol( nNewCol ),
      62                 :            :     nTab( nNewTab ),
      63                 :    1982464 :     pDocument( pDoc )
      64                 :            : {
      65                 :    1982464 :     nCount = nLimit = 1;
      66                 :    1982464 :     pData = new ScAttrEntry[1];
      67         [ +  - ]:    1982464 :     if (pData)
      68                 :            :     {
      69                 :    1982464 :         pData[0].nRow = MAXROW;
      70                 :    1982464 :         pData[0].pPattern = pDocument->GetDefPattern(); // no put
      71                 :            :     }
      72                 :    1982464 : }
      73                 :            : 
      74                 :            : //------------------------------------------------------------------------
      75                 :            : 
      76                 :    1787904 : ScAttrArray::~ScAttrArray()
      77                 :            : {
      78                 :            : #if OSL_DEBUG_LEVEL > 1
      79                 :            :     TestData();
      80                 :            : #endif
      81                 :            : 
      82         [ +  - ]:    1787904 :     if (pData)
      83                 :            :     {
      84                 :    1787904 :         ScDocumentPool* pDocPool = pDocument->GetPool();
      85         [ +  + ]:    3587934 :         for (SCSIZE i=0; i<nCount; i++)
      86                 :    1800030 :             pDocPool->Remove(*pData[i].pPattern);
      87                 :            : 
      88         [ +  - ]:    1787904 :         delete[] pData;
      89                 :            :     }
      90                 :    1787904 : }
      91                 :            : 
      92                 :            : //------------------------------------------------------------------------
      93                 :            : #if OSL_DEBUG_LEVEL > 1
      94                 :            : void ScAttrArray::TestData() const
      95                 :            : {
      96                 :            : 
      97                 :            :     sal_uInt16 nErr = 0;
      98                 :            :     if (pData)
      99                 :            :     {
     100                 :            :         SCSIZE nPos;
     101                 :            :         for (nPos=0; nPos<nCount; nPos++)
     102                 :            :         {
     103                 :            :             if (nPos > 0)
     104                 :            :                 if (pData[nPos].pPattern == pData[nPos-1].pPattern || pData[nPos].nRow <= pData[nPos-1].nRow)
     105                 :            :                     ++nErr;
     106                 :            :             if (pData[nPos].pPattern->Which() != ATTR_PATTERN)
     107                 :            :                 ++nErr;
     108                 :            :         }
     109                 :            :         if ( nPos && pData[nPos-1].nRow != MAXROW )
     110                 :            :             ++nErr;
     111                 :            :     }
     112                 :            :     if (nErr)
     113                 :            :     {
     114                 :            :         rtl::OStringBuffer aMsg;
     115                 :            :         aMsg.append(static_cast<sal_Int32>(nErr));
     116                 :            :         aMsg.append(RTL_CONSTASCII_STRINGPARAM(
     117                 :            :             " errors in attribute array, column "));
     118                 :            :         aMsg.append(static_cast<sal_Int32>(nCol));
     119                 :            :         OSL_FAIL(aMsg.getStr());
     120                 :            :     }
     121                 :            : }
     122                 :            : #endif
     123                 :            : 
     124                 :            : //------------------------------------------------------------------------
     125                 :            : 
     126                 :      42925 : void ScAttrArray::Reset( const ScPatternAttr* pPattern, bool bAlloc )
     127                 :            : {
     128         [ +  - ]:      42925 :     if (pData)
     129                 :            :     {
     130         [ +  - ]:      42925 :         ScDocumentPool*      pDocPool = pDocument->GetPool();
     131                 :            :         const ScPatternAttr* pOldPattern;
     132                 :      42925 :         ScAddress            aAdrStart( nCol, 0, nTab );
     133                 :      42925 :         ScAddress            aAdrEnd  ( nCol, 0, nTab );
     134                 :            : 
     135         [ +  + ]:      85850 :         for (SCSIZE i=0; i<nCount; i++)
     136                 :            :         {
     137                 :            :             // ensure that attributing changes text width of cell
     138                 :      42925 :             pOldPattern = pData[i].pPattern;
     139                 :            :             bool bNumFormatChanged;
     140         [ -  + ]:      42925 :             if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
     141         [ +  - ]:      42925 :                     pPattern->GetItemSet(), pOldPattern->GetItemSet() ) )
     142                 :            :             {
     143         [ #  # ]:          0 :                 aAdrStart.SetRow( i ? pData[i-1].nRow+1 : 0 );
     144                 :          0 :                 aAdrEnd  .SetRow( pData[i].nRow );
     145         [ #  # ]:          0 :                 pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
     146                 :            :             }
     147         [ +  - ]:      42925 :             pDocPool->Remove(*pOldPattern);
     148                 :            :         }
     149         [ +  - ]:      42925 :         delete[] pData;
     150                 :            : 
     151 [ +  - ][ -  + ]:      42925 :         if (pDocument->IsStreamValid(nTab))
     152         [ #  # ]:          0 :             pDocument->SetStreamValid(nTab, false);
     153                 :            : 
     154         [ +  - ]:      42925 :         if (bAlloc)
     155                 :            :         {
     156                 :      42925 :             nCount = nLimit = 1;
     157         [ +  - ]:      42925 :             pData = new ScAttrEntry[1];
     158         [ +  - ]:      42925 :             if (pData)
     159                 :            :             {
     160         [ +  - ]:      42925 :                 ScPatternAttr* pNewPattern = (ScPatternAttr*) &pDocPool->Put(*pPattern);
     161                 :      42925 :                 pData[0].nRow = MAXROW;
     162                 :      42925 :                 pData[0].pPattern = pNewPattern;
     163                 :            :             }
     164                 :            :         }
     165                 :            :         else
     166                 :            :         {
     167                 :          0 :             nCount = nLimit = 0;
     168                 :      42925 :             pData = NULL;        // should be immediately occupied again
     169                 :            :         }
     170                 :            :     }
     171                 :      42925 : }
     172                 :            : 
     173                 :            : 
     174                 :      49535 : bool ScAttrArray::Concat(SCSIZE nPos)
     175                 :            : {
     176                 :      49535 :     bool bRet = false;
     177 [ +  - ][ +  - ]:      49535 :     if (pData && (nPos < nCount))
     178                 :            :     {
     179         [ +  + ]:      49535 :         if (nPos > 0)
     180                 :            :         {
     181         [ -  + ]:        167 :             if (pData[nPos - 1].pPattern == pData[nPos].pPattern)
     182                 :            :             {
     183                 :          0 :                 pData[nPos - 1].nRow = pData[nPos].nRow;
     184                 :          0 :                 pDocument->GetPool()->Remove(*pData[nPos].pPattern);
     185                 :          0 :                 memmove(&pData[nPos], &pData[nPos + 1], (nCount - nPos - 1) * sizeof(ScAttrEntry));
     186                 :          0 :                 pData[nCount - 1].pPattern = NULL;
     187                 :          0 :                 pData[nCount - 1].nRow = 0;
     188                 :          0 :                 nCount--;
     189                 :          0 :                 nPos--;
     190                 :          0 :                 bRet = true;
     191                 :            :             }
     192                 :            :         }
     193         [ +  + ]:      49535 :         if (nPos + 1 < nCount)
     194                 :            :         {
     195         [ -  + ]:       1913 :             if (pData[nPos + 1].pPattern == pData[nPos].pPattern)
     196                 :            :             {
     197                 :          0 :                 pData[nPos].nRow = pData[nPos + 1].nRow;
     198                 :          0 :                 pDocument->GetPool()->Remove(*pData[nPos].pPattern);
     199                 :          0 :                 memmove(&pData[nPos + 1], &pData[nPos + 2], (nCount - nPos - 2) * sizeof(ScAttrEntry));
     200                 :          0 :                 pData[nCount - 1].pPattern = NULL;
     201                 :          0 :                 pData[nCount - 1].nRow = 0;
     202                 :          0 :                 nCount--;
     203                 :          0 :                 bRet = true;
     204                 :            :             }
     205                 :            :         }
     206                 :            :     }
     207                 :      49535 :     return bRet;
     208                 :            : }
     209                 :            : 
     210                 :            : //------------------------------------------------------------------------
     211                 :            : 
     212                 :   16905770 : bool ScAttrArray::Search( SCROW nRow, SCSIZE& nIndex ) const
     213                 :            : {
     214                 :   16905770 :     long    nHi         = static_cast<long>(nCount) - 1;
     215                 :   16905770 :     long    i           = 0;
     216                 :   16905770 :     bool    bFound      = (nCount == 1);
     217         [ +  - ]:   16905770 :     if (pData)
     218                 :            :     {
     219                 :   16905770 :         long nLo = 0;
     220                 :   16905770 :         long nStartRow = 0;
     221                 :   16905770 :         long nEndRow = 0;
     222 [ +  + ][ +  + ]:   17097551 :         while ( !bFound && nLo <= nHi )
                 [ +  + ]
     223                 :            :         {
     224                 :     191781 :             i = (nLo + nHi) / 2;
     225         [ +  + ]:     191781 :             if (i > 0)
     226                 :     153788 :                 nStartRow = (long) pData[i - 1].nRow;
     227                 :            :             else
     228                 :      37993 :                 nStartRow = -1;
     229                 :     191781 :             nEndRow = (long) pData[i].nRow;
     230         [ +  + ]:     191781 :             if (nEndRow < (long) nRow)
     231                 :      65454 :                 nLo = ++i;
     232                 :            :             else
     233         [ +  + ]:     126327 :                 if (nStartRow >= (long) nRow)
     234                 :      34812 :                     nHi = --i;
     235                 :            :                 else
     236                 :      91515 :                     bFound = true;
     237                 :            :         }
     238                 :            :     }
     239                 :            :     else
     240                 :          0 :         bFound = false;
     241                 :            : 
     242         [ +  + ]:   16905770 :     if (bFound)
     243                 :   16903206 :         nIndex=(SCSIZE)i;
     244                 :            :     else
     245                 :       2564 :         nIndex=0;
     246                 :   16905770 :     return bFound;
     247                 :            : }
     248                 :            : 
     249                 :            : 
     250                 :      88851 : const ScPatternAttr* ScAttrArray::GetPattern( SCROW nRow ) const
     251                 :            : {
     252                 :            :     SCSIZE i;
     253         [ +  - ]:      88851 :     if (Search( nRow, i ))
     254                 :      88851 :         return pData[i].pPattern;
     255                 :            :     else
     256                 :      88851 :         return NULL;
     257                 :            : }
     258                 :            : 
     259                 :            : 
     260                 :          0 : const ScPatternAttr* ScAttrArray::GetPatternRange( SCROW& rStartRow,
     261                 :            :         SCROW& rEndRow, SCROW nRow ) const
     262                 :            : {
     263                 :            :     SCSIZE nIndex;
     264         [ #  # ]:          0 :     if ( Search( nRow, nIndex ) )
     265                 :            :     {
     266         [ #  # ]:          0 :         if ( nIndex > 0 )
     267                 :          0 :             rStartRow = pData[nIndex-1].nRow + 1;
     268                 :            :         else
     269                 :          0 :             rStartRow = 0;
     270                 :          0 :         rEndRow = pData[nIndex].nRow;
     271                 :          0 :         return pData[nIndex].pPattern;
     272                 :            :     }
     273                 :          0 :     return NULL;
     274                 :            : }
     275                 :            : 
     276                 :            : //------------------------------------------------------------------------
     277                 :            : 
     278                 :       1140 : void ScAttrArray::SetPattern( SCROW nRow, const ScPatternAttr* pPattern, bool bPutToPool )
     279                 :            : {
     280                 :       1140 :     SetPatternArea( nRow, nRow, pPattern, bPutToPool );
     281                 :       1140 : }
     282                 :            : 
     283                 :          0 : void ScAttrArray::RemoveCellCharAttribs( SCROW nStartRow, SCROW nEndRow,
     284                 :            :                                        const ScPatternAttr* pPattern, ScEditDataArray* pDataArray )
     285                 :            : {
     286         [ #  # ]:          0 :     for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
     287                 :            :     {
     288                 :            :         ScBaseCell* pCell;
     289         [ #  # ]:          0 :         pDocument->GetCell(nCol, nRow, nTab, pCell);
     290 [ #  # ][ #  # ]:          0 :         if (pCell && pCell->GetCellType() == CELLTYPE_EDIT)
                 [ #  # ]
     291                 :            :         {
     292                 :          0 :             EditTextObject* pOldData = NULL;
     293                 :          0 :             ScEditCell* pEditCell = static_cast<ScEditCell*>(pCell);
     294         [ #  # ]:          0 :             if (pDataArray)
     295         [ #  # ]:          0 :                 pOldData = pEditCell->GetData()->Clone();
     296         [ #  # ]:          0 :             pEditCell->RemoveCharAttribs(*pPattern);
     297         [ #  # ]:          0 :             if (pDataArray)
     298                 :            :             {
     299         [ #  # ]:          0 :                 EditTextObject* pNewData = pEditCell->GetData()->Clone();
     300         [ #  # ]:          0 :                 pDataArray->AddItem(nTab, nCol, nRow, pOldData, pNewData);
     301                 :            :             }
     302                 :            :         }
     303                 :            :     }
     304                 :          0 : }
     305                 :            : 
     306                 :      82311 : void ScAttrArray::SetPatternArea(SCROW nStartRow, SCROW nEndRow, const ScPatternAttr *pPattern,
     307                 :            :                                  bool bPutToPool, ScEditDataArray* pDataArray )
     308                 :            : {
     309 [ +  - ][ +  - ]:      82311 :     if (ValidRow(nStartRow) && ValidRow(nEndRow))
                 [ +  - ]
     310                 :            :     {
     311         [ +  + ]:      82311 :         if (bPutToPool)
     312                 :      12106 :             pPattern = (const ScPatternAttr*) &pDocument->GetPool()->Put(*pPattern);
     313                 :            : 
     314 [ +  + ][ +  + ]:      82311 :         if ((nStartRow == 0) && (nEndRow == MAXROW))
     315                 :      42925 :             Reset(pPattern);
     316                 :            :         else
     317                 :            :         {
     318                 :      39386 :             SCSIZE nNeeded = nCount + 2;
     319         [ +  + ]:      39386 :             if ( nLimit < nNeeded )
     320                 :            :             {
     321                 :      18864 :                 nLimit += SC_ATTRARRAY_DELTA;
     322         [ -  + ]:      18864 :                 if ( nLimit < nNeeded )
     323                 :          0 :                     nLimit = nNeeded;
     324         [ +  - ]:      18864 :                 ScAttrEntry* pNewData = new ScAttrEntry[nLimit];
     325                 :      18864 :                 memcpy( pNewData, pData, nCount*sizeof(ScAttrEntry) );
     326         [ +  - ]:      18864 :                 delete[] pData;
     327                 :      18864 :                 pData = pNewData;
     328                 :            :             }
     329                 :            : 
     330                 :      39386 :             ScAddress       aAdrStart( nCol, 0, nTab );
     331                 :      39386 :             ScAddress       aAdrEnd  ( nCol, 0, nTab );
     332                 :            : 
     333                 :      39386 :             SCSIZE ni = 0;      // number of entries in beginning
     334                 :      39386 :             SCSIZE nx = 0;      // track position
     335                 :      39386 :             SCROW ns = 0;      // start row of track position
     336         [ +  + ]:      39386 :             if ( nStartRow > 0 )
     337                 :            :             {
     338                 :            :                 // skip beginning
     339                 :            :                 SCSIZE nIndex;
     340                 :      26832 :                 Search( nStartRow, nIndex );
     341                 :      26832 :                 ni = nIndex;
     342                 :            : 
     343         [ +  + ]:      26832 :                 if ( ni > 0 )
     344                 :            :                 {
     345                 :      15967 :                     nx = ni;
     346                 :      26832 :                     ns = pData[ni-1].nRow+1;
     347                 :            :                 }
     348                 :            :             }
     349                 :            : 
     350                 :            :             // ensure that attributing changes text width of cell
     351                 :            :             // otherwise, conditional formats need to be reset or deleted
     352         [ +  + ]:      80869 :             while ( ns <= nEndRow )
     353                 :            :             {
     354                 :      41483 :                 const SfxItemSet& rNewSet = pPattern->GetItemSet();
     355                 :      41483 :                 const SfxItemSet& rOldSet = pData[nx].pPattern->GetItemSet();
     356                 :            : 
     357                 :            :                 bool bNumFormatChanged;
     358         [ +  + ]:      41483 :                 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
     359         [ +  - ]:      41483 :                         rNewSet, rOldSet ) )
     360                 :            :                 {
     361                 :       4791 :                     aAdrStart.SetRow( Max(nStartRow,ns) );
     362                 :       4791 :                     aAdrEnd  .SetRow( Min(nEndRow,pData[nx].nRow) );
     363         [ +  - ]:       4791 :                     pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
     364                 :            :                 }
     365                 :      41483 :                 ns = pData[nx].nRow + 1;
     366                 :      41483 :                 nx++;
     367                 :            :             }
     368                 :            : 
     369                 :            :             // continue modifying data array
     370                 :            : 
     371                 :            :             SCSIZE nInsert;     // insert position (MAXROWCOUNT := no insert)
     372                 :      39386 :             bool bCombined = false;
     373                 :      39386 :             bool bSplit = false;
     374         [ +  + ]:      39386 :             if ( nStartRow > 0 )
     375                 :            :             {
     376                 :      26832 :                 nInsert = MAXROWCOUNT;
     377         [ +  + ]:      26832 :                 if ( pData[ni].pPattern != pPattern )
     378                 :            :                 {
     379 [ +  + ][ +  + ]:      17764 :                     if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
     380                 :            :                     {   // may be a split or a simple insert or just a shrink,
     381                 :            :                         // row adjustment is done further down
     382         [ +  + ]:       3161 :                         if ( pData[ni].nRow > nEndRow )
     383                 :       1993 :                             bSplit = true;
     384                 :       3161 :                         ni++;
     385                 :       3161 :                         nInsert = ni;
     386                 :            :                     }
     387 [ +  - ][ +  - ]:      14603 :                     else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
     388                 :      17764 :                         nInsert = ni;
     389                 :            :                 }
     390 [ +  + ][ +  + ]:      26832 :                 if ( ni > 0 && pData[ni-1].pPattern == pPattern )
     391                 :            :                 {   // combine
     392                 :       1668 :                     pData[ni-1].nRow = nEndRow;
     393                 :       1668 :                     nInsert = MAXROWCOUNT;
     394                 :       1668 :                     bCombined = true;
     395                 :            :                 }
     396                 :            :             }
     397                 :            :             else
     398                 :      12554 :                 nInsert = 0;
     399                 :            : 
     400                 :      39386 :             SCSIZE nj = ni;     // stop position of range to replace
     401 [ +  + ][ +  + ]:      52827 :             while ( nj < nCount && pData[nj].nRow <= nEndRow )
                 [ +  + ]
     402                 :      13441 :                 nj++;
     403         [ +  + ]:      39386 :             if ( !bSplit )
     404                 :            :             {
     405 [ +  + ][ +  + ]:      37393 :                 if ( nj < nCount && pData[nj].pPattern == pPattern )
     406                 :            :                 {   // combine
     407         [ +  + ]:      16588 :                     if ( ni > 0 )
     408                 :            :                     {
     409         [ +  + ]:        333 :                         if ( pData[ni-1].pPattern == pPattern )
     410                 :            :                         {   // adjacent entries
     411                 :        231 :                             pData[ni-1].nRow = pData[nj].nRow;
     412                 :        231 :                             nj++;
     413                 :            :                         }
     414         [ +  + ]:        102 :                         else if ( ni == nInsert )
     415                 :         18 :                             pData[ni-1].nRow = nStartRow - 1;   // shrink
     416                 :            :                     }
     417                 :      16588 :                     nInsert = MAXROWCOUNT;
     418                 :      16588 :                     bCombined = true;
     419                 :            :                 }
     420 [ +  + ][ +  + ]:      20805 :                 else if ( ni > 0 && ni == nInsert )
     421                 :      37393 :                     pData[ni-1].nRow = nStartRow - 1;   // shrink
     422                 :            :             }
     423         [ +  - ]:      39386 :             ScDocumentPool* pDocPool = pDocument->GetPool();
     424         [ +  + ]:      39386 :             if ( bSplit )
     425                 :            :             {   // duplicate splitted entry in pool
     426         [ +  - ]:       1993 :                 pDocPool->Put( *pData[ni-1].pPattern );
     427                 :            :             }
     428         [ +  + ]:      39386 :             if ( ni < nj )
     429                 :            :             {   // remove middle entries
     430         [ +  + ]:      25044 :                 for ( SCSIZE nk=ni; nk<nj; nk++)
     431                 :            :                 {   // remove entries from pool
     432         [ +  - ]:      13672 :                     pDocPool->Remove( *pData[nk].pPattern );
     433                 :            :                 }
     434         [ +  + ]:      11372 :                 if ( !bCombined )
     435                 :            :                 {   // replace one entry
     436                 :      10592 :                     pData[ni].nRow = nEndRow;
     437                 :      10592 :                     pData[ni].pPattern = pPattern;
     438                 :      10592 :                     ni++;
     439                 :      10592 :                     nInsert = MAXROWCOUNT;
     440                 :            :                 }
     441         [ +  + ]:      11372 :                 if ( ni < nj )
     442                 :            :                 {   // remove entries
     443                 :        784 :                     memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScAttrEntry) );
     444                 :        784 :                     nCount -= nj - ni;
     445                 :            :                 }
     446                 :            :             }
     447                 :            : 
     448         [ +  + ]:      39386 :             if ( nInsert < sal::static_int_cast<SCSIZE>(MAXROWCOUNT) )
     449                 :            :             {   // insert or append new entry
     450         [ +  - ]:      10769 :                 if ( nInsert <= nCount )
     451                 :            :                 {
     452         [ +  + ]:      10769 :                     if ( !bSplit )
     453                 :       8776 :                         memmove( pData + nInsert + 1, pData + nInsert,
     454                 :       8776 :                             (nCount - nInsert) * sizeof(ScAttrEntry) );
     455                 :            :                     else
     456                 :            :                     {
     457                 :       1993 :                         memmove( pData + nInsert + 2, pData + nInsert,
     458                 :       3986 :                             (nCount - nInsert) * sizeof(ScAttrEntry) );
     459                 :       1993 :                         pData[nInsert+1] = pData[nInsert-1];
     460                 :       1993 :                         nCount++;
     461                 :            :                     }
     462                 :            :                 }
     463         [ +  + ]:      10769 :                 if ( nInsert )
     464                 :       8269 :                     pData[nInsert-1].nRow = nStartRow - 1;
     465                 :      10769 :                 pData[nInsert].nRow = nEndRow;
     466                 :      10769 :                 pData[nInsert].pPattern = pPattern;
     467                 :            : 
     468                 :            :                 // Remove character attributes from these cells if the pattern
     469                 :            :                 // is applied during normal session.
     470         [ -  + ]:      10769 :                 if (pDataArray)
     471         [ #  # ]:          0 :                     RemoveCellCharAttribs(nStartRow, nEndRow, pPattern, pDataArray);
     472                 :            : 
     473                 :      10769 :                 nCount++;
     474                 :            :             }
     475                 :            : 
     476 [ +  - ][ +  + ]:      39386 :             if (pDocument->IsStreamValid(nTab))
     477         [ +  - ]:      82311 :                 pDocument->SetStreamValid(nTab, false);
     478                 :            :         }
     479                 :            :     }
     480                 :            : 
     481                 :            : #if OSL_DEBUG_LEVEL > 1
     482                 :            :     TestData();
     483                 :            : #endif
     484                 :      82311 : }
     485                 :            : 
     486                 :            : 
     487                 :       7013 : void ScAttrArray::ApplyStyleArea( SCROW nStartRow, SCROW nEndRow, ScStyleSheet* pStyle )
     488                 :            : {
     489 [ +  - ][ +  - ]:       7013 :     if (ValidRow(nStartRow) && ValidRow(nEndRow))
                 [ +  - ]
     490                 :            :     {
     491                 :            :         SCSIZE nPos;
     492                 :       7013 :         SCROW nStart=0;
     493         [ +  - ]:       7013 :         if (!Search( nStartRow, nPos ))
     494                 :            :         {
     495                 :            :             OSL_FAIL("Search Failure");
     496                 :       7013 :             return;
     497                 :            :         }
     498                 :            : 
     499                 :       7013 :         ScAddress aAdrStart( nCol, 0, nTab );
     500                 :       7013 :         ScAddress aAdrEnd  ( nCol, 0, nTab );
     501                 :            : 
     502 [ +  + ][ +  - ]:       7281 :         do
                 [ +  + ]
     503                 :            :         {
     504                 :       7281 :             const ScPatternAttr* pOldPattern = pData[nPos].pPattern;
     505 [ +  - ][ +  - ]:       7281 :             ScPatternAttr* pNewPattern = new ScPatternAttr(*pOldPattern);
     506         [ +  - ]:       7281 :             pNewPattern->SetStyleSheet(pStyle);
     507                 :       7281 :             SCROW nY1 = nStart;
     508                 :       7281 :             SCROW nY2 = pData[nPos].nRow;
     509                 :       7281 :             nStart = pData[nPos].nRow + 1;
     510                 :            : 
     511 [ +  - ][ +  + ]:       7281 :             if ( *pNewPattern == *pOldPattern )
     512                 :            :             {
     513                 :            :                 // keep the original pattern (might be default)
     514                 :            :                 // pNewPattern is deleted below
     515                 :       4078 :                 nPos++;
     516                 :            :             }
     517 [ +  + ][ +  + ]:       3203 :             else if ( nY1 < nStartRow || nY2 > nEndRow )
     518                 :            :             {
     519         [ +  + ]:       3010 :                 if (nY1 < nStartRow) nY1=nStartRow;
     520         [ +  + ]:       3010 :                 if (nY2 > nEndRow) nY2=nEndRow;
     521         [ +  - ]:       3010 :                 SetPatternArea( nY1, nY2, pNewPattern, true );
     522                 :       3010 :                 Search( nStart, nPos );
     523                 :            :             }
     524                 :            :             else
     525                 :            :             {
     526                 :            :                 // ensure attributing changes text width of cell; otherwise
     527                 :            :                 // there aren't (yet) template format changes
     528                 :        193 :                 const SfxItemSet& rNewSet = pNewPattern->GetItemSet();
     529                 :        193 :                 const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
     530                 :            : 
     531                 :            :                 bool bNumFormatChanged;
     532         [ +  + ]:        193 :                 if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
     533         [ +  - ]:        193 :                         rNewSet, rOldSet ) )
     534                 :            :                 {
     535         [ +  - ]:          7 :                     aAdrStart.SetRow( nPos ? pData[nPos-1].nRow+1 : 0 );
     536                 :          7 :                     aAdrEnd  .SetRow( pData[nPos].nRow );
     537         [ +  - ]:          7 :                     pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
     538                 :            :                 }
     539                 :            : 
     540 [ +  - ][ +  - ]:        193 :                 pDocument->GetPool()->Remove(*pData[nPos].pPattern);
     541                 :        193 :                 pData[nPos].pPattern = (const ScPatternAttr*)
     542 [ +  - ][ +  - ]:        193 :                                             &pDocument->GetPool()->Put(*pNewPattern);
     543 [ +  - ][ -  + ]:        193 :                 if (Concat(nPos))
     544                 :          0 :                     Search(nStart, nPos);
     545                 :            :                 else
     546                 :        193 :                     nPos++;
     547                 :            :             }
     548 [ +  - ][ +  - ]:       7281 :             delete pNewPattern;
     549                 :            :         }
     550                 :            :         while ((nStart <= nEndRow) && (nPos < nCount));
     551                 :            : 
     552 [ +  - ][ -  + ]:       7013 :         if (pDocument->IsStreamValid(nTab))
     553         [ #  # ]:       7013 :             pDocument->SetStreamValid(nTab, false);
     554                 :            :     }
     555                 :            : 
     556                 :            : #if OSL_DEBUG_LEVEL > 1
     557                 :            :     TestData();
     558                 :            : #endif
     559                 :            : }
     560                 :            : 
     561                 :            : 
     562                 :            :     // const cast, otherwise it will be too inefficient/complicated
     563                 :            : #define SET_LINECOLOR(dest,c)                    \
     564                 :            :     if ((dest))                                  \
     565                 :            :     {                                            \
     566                 :            :         ((SvxBorderLine*)(dest))->SetColor((c)); \
     567                 :            :     }
     568                 :            : 
     569                 :            : #define SET_LINE(dest,src)                             \
     570                 :            :     if ((dest))                                        \
     571                 :            :     {                                                  \
     572                 :            :         SvxBorderLine* pCast = (SvxBorderLine*)(dest); \
     573                 :            :         pCast->SetBorderLineStyle( (src)->GetBorderLineStyle() ); \
     574                 :            :         pCast->SetWidth( (src)->GetWidth( ) );         \
     575                 :            :     }
     576                 :            : 
     577                 :          0 : void ScAttrArray::ApplyLineStyleArea( SCROW nStartRow, SCROW nEndRow,
     578                 :            :                                       const SvxBorderLine* pLine, bool bColorOnly )
     579                 :            : {
     580 [ #  # ][ #  # ]:          0 :     if ( bColorOnly && !pLine )
     581                 :          0 :         return;
     582                 :            : 
     583 [ #  # ][ #  # ]:          0 :     if (ValidRow(nStartRow) && ValidRow(nEndRow))
                 [ #  # ]
     584                 :            :     {
     585                 :            :         SCSIZE nPos;
     586                 :          0 :         SCROW nStart=0;
     587         [ #  # ]:          0 :         if (!Search( nStartRow, nPos ))
     588                 :            :         {
     589                 :            :             OSL_FAIL("Search failure");
     590                 :            :             return;
     591                 :            :         }
     592                 :            : 
     593 [ #  # ][ #  # ]:          0 :         do
                 [ #  # ]
     594                 :            :         {
     595                 :          0 :             const ScPatternAttr*    pOldPattern = pData[nPos].pPattern;
     596                 :          0 :             const SfxItemSet&       rOldSet = pOldPattern->GetItemSet();
     597                 :          0 :             const SfxPoolItem*      pBoxItem = 0;
     598         [ #  # ]:          0 :             SfxItemState            eState = rOldSet.GetItemState( ATTR_BORDER, true, &pBoxItem );
     599                 :          0 :             const SfxPoolItem*      pTLBRItem = 0;
     600         [ #  # ]:          0 :             SfxItemState            eTLBRState = rOldSet.GetItemState( ATTR_BORDER_TLBR, true, &pTLBRItem );
     601                 :          0 :             const SfxPoolItem*      pBLTRItem = 0;
     602         [ #  # ]:          0 :             SfxItemState            eBLTRState = rOldSet.GetItemState( ATTR_BORDER_BLTR, true, &pBLTRItem );
     603                 :            : 
     604 [ #  # ][ #  # ]:          0 :             if ( (SFX_ITEM_SET == eState) || (SFX_ITEM_SET == eTLBRState) || (SFX_ITEM_SET == eBLTRState) )
                 [ #  # ]
     605                 :            :             {
     606 [ #  # ][ #  # ]:          0 :                 ScPatternAttr*  pNewPattern = new ScPatternAttr(*pOldPattern);
     607                 :          0 :                 SfxItemSet&     rNewSet = pNewPattern->GetItemSet();
     608                 :          0 :                 SCROW           nY1 = nStart;
     609                 :          0 :                 SCROW           nY2 = pData[nPos].nRow;
     610                 :            : 
     611 [ #  # ][ #  # ]:          0 :                 SvxBoxItem*     pNewBoxItem = pBoxItem ? (SvxBoxItem*)pBoxItem->Clone() : 0;
     612 [ #  # ][ #  # ]:          0 :                 SvxLineItem*    pNewTLBRItem = pTLBRItem ? (SvxLineItem*)pTLBRItem->Clone() : 0;
     613 [ #  # ][ #  # ]:          0 :                 SvxLineItem*    pNewBLTRItem = pBLTRItem ? (SvxLineItem*)pBLTRItem->Clone() : 0;
     614                 :            : 
     615                 :            :                 // fetch line and update attributes with parameters
     616                 :            : 
     617         [ #  # ]:          0 :                 if ( !pLine )
     618                 :            :                 {
     619         [ #  # ]:          0 :                     if( pNewBoxItem )
     620                 :            :                     {
     621 [ #  # ][ #  # ]:          0 :                         if ( pNewBoxItem->GetTop() )    pNewBoxItem->SetLine( NULL, BOX_LINE_TOP );
     622 [ #  # ][ #  # ]:          0 :                         if ( pNewBoxItem->GetBottom() ) pNewBoxItem->SetLine( NULL, BOX_LINE_BOTTOM );
     623 [ #  # ][ #  # ]:          0 :                         if ( pNewBoxItem->GetLeft() )   pNewBoxItem->SetLine( NULL, BOX_LINE_LEFT );
     624 [ #  # ][ #  # ]:          0 :                         if ( pNewBoxItem->GetRight() )  pNewBoxItem->SetLine( NULL, BOX_LINE_RIGHT );
     625                 :            :                     }
     626 [ #  # ][ #  # ]:          0 :                     if( pNewTLBRItem && pNewTLBRItem->GetLine() )
                 [ #  # ]
     627         [ #  # ]:          0 :                         pNewTLBRItem->SetLine( 0 );
     628 [ #  # ][ #  # ]:          0 :                     if( pNewBLTRItem && pNewBLTRItem->GetLine() )
                 [ #  # ]
     629         [ #  # ]:          0 :                         pNewBLTRItem->SetLine( 0 );
     630                 :            :                 }
     631                 :            :                 else
     632                 :            :                 {
     633         [ #  # ]:          0 :                     if ( bColorOnly )
     634                 :            :                     {
     635                 :          0 :                         Color aColor( pLine->GetColor() );
     636         [ #  # ]:          0 :                         if( pNewBoxItem )
     637                 :            :                         {
     638         [ #  # ]:          0 :                             SET_LINECOLOR( pNewBoxItem->GetTop(),    aColor );
     639         [ #  # ]:          0 :                             SET_LINECOLOR( pNewBoxItem->GetBottom(), aColor );
     640         [ #  # ]:          0 :                             SET_LINECOLOR( pNewBoxItem->GetLeft(),   aColor );
     641         [ #  # ]:          0 :                             SET_LINECOLOR( pNewBoxItem->GetRight(),   aColor );
     642                 :            :                         }
     643         [ #  # ]:          0 :                         if( pNewTLBRItem )
     644         [ #  # ]:          0 :                             SET_LINECOLOR( pNewTLBRItem->GetLine(), aColor );
     645         [ #  # ]:          0 :                         if( pNewBLTRItem )
     646         [ #  # ]:          0 :                             SET_LINECOLOR( pNewBLTRItem->GetLine(), aColor );
     647                 :            :                     }
     648                 :            :                     else
     649                 :            :                     {
     650         [ #  # ]:          0 :                         if( pNewBoxItem )
     651                 :            :                         {
     652 [ #  # ][ #  # ]:          0 :                             SET_LINE( pNewBoxItem->GetTop(),    pLine );
     653 [ #  # ][ #  # ]:          0 :                             SET_LINE( pNewBoxItem->GetBottom(), pLine );
     654 [ #  # ][ #  # ]:          0 :                             SET_LINE( pNewBoxItem->GetLeft(),   pLine );
     655 [ #  # ][ #  # ]:          0 :                             SET_LINE( pNewBoxItem->GetRight(),   pLine );
     656                 :            :                         }
     657         [ #  # ]:          0 :                         if( pNewTLBRItem )
     658 [ #  # ][ #  # ]:          0 :                             SET_LINE( pNewTLBRItem->GetLine(), pLine );
     659         [ #  # ]:          0 :                         if( pNewBLTRItem )
     660 [ #  # ][ #  # ]:          0 :                             SET_LINE( pNewBLTRItem->GetLine(), pLine );
     661                 :            :                     }
     662                 :            :                 }
     663 [ #  # ][ #  # ]:          0 :                 if( pNewBoxItem )   rNewSet.Put( *pNewBoxItem );
     664 [ #  # ][ #  # ]:          0 :                 if( pNewTLBRItem )  rNewSet.Put( *pNewTLBRItem );
     665 [ #  # ][ #  # ]:          0 :                 if( pNewBLTRItem )  rNewSet.Put( *pNewBLTRItem );
     666                 :            : 
     667                 :          0 :                 nStart = pData[nPos].nRow + 1;
     668                 :            : 
     669 [ #  # ][ #  # ]:          0 :                 if ( nY1 < nStartRow || nY2 > nEndRow )
     670                 :            :                 {
     671         [ #  # ]:          0 :                     if (nY1 < nStartRow) nY1=nStartRow;
     672         [ #  # ]:          0 :                     if (nY2 > nEndRow) nY2=nEndRow;
     673         [ #  # ]:          0 :                     SetPatternArea( nY1, nY2, pNewPattern, true );
     674                 :          0 :                     Search( nStart, nPos );
     675                 :            :                 }
     676                 :            :                 else
     677                 :            :                 {
     678                 :            :                     // remove from pool ?
     679 [ #  # ][ #  # ]:          0 :                     pDocument->GetPool()->Remove(*pData[nPos].pPattern);
     680                 :          0 :                     pData[nPos].pPattern = (const ScPatternAttr*)
     681 [ #  # ][ #  # ]:          0 :                                 &pDocument->GetPool()->Put(*pNewPattern);
     682                 :            : 
     683 [ #  # ][ #  # ]:          0 :                     if (Concat(nPos))
     684                 :          0 :                         Search(nStart, nPos);
     685                 :            :                     else
     686                 :          0 :                         nPos++;
     687                 :            :                 }
     688 [ #  # ][ #  # ]:          0 :                 delete pNewBoxItem;
     689 [ #  # ][ #  # ]:          0 :                 delete pNewTLBRItem;
     690 [ #  # ][ #  # ]:          0 :                 delete pNewBLTRItem;
     691 [ #  # ][ #  # ]:          0 :                 delete pNewPattern;
     692                 :            :             }
     693                 :            :             else
     694                 :            :             {
     695                 :          0 :                 nStart = pData[nPos].nRow + 1;
     696                 :          0 :                 nPos++;
     697                 :            :             }
     698                 :            :         }
     699                 :            :         while ((nStart <= nEndRow) && (nPos < nCount));
     700                 :            :     }
     701                 :            : }
     702                 :            : 
     703                 :            : #undef SET_LINECOLOR
     704                 :            : #undef SET_LINE
     705                 :            : 
     706                 :            : 
     707                 :      54867 : void ScAttrArray::ApplyCacheArea( SCROW nStartRow, SCROW nEndRow, SfxItemPoolCache* pCache, ScEditDataArray* pDataArray )
     708                 :            : {
     709                 :            : #if OSL_DEBUG_LEVEL > 1
     710                 :            :     TestData();
     711                 :            : #endif
     712                 :            : 
     713 [ +  - ][ +  - ]:      54867 :     if (ValidRow(nStartRow) && ValidRow(nEndRow))
                 [ +  - ]
     714                 :            :     {
     715                 :            :         SCSIZE nPos;
     716                 :      54867 :         SCROW nStart=0;
     717         [ +  - ]:      54867 :         if (!Search( nStartRow, nPos ))
     718                 :            :         {
     719                 :            :             OSL_FAIL("Search Failure");
     720                 :      54867 :             return;
     721                 :            :         }
     722                 :            : 
     723                 :      54867 :         ScAddress aAdrStart( nCol, 0, nTab );
     724                 :      54867 :         ScAddress aAdrEnd  ( nCol, 0, nTab );
     725                 :            : 
     726         [ +  + ]:      54921 :         do
     727                 :            :         {
     728                 :      54921 :             const ScPatternAttr* pOldPattern = pData[nPos].pPattern;
     729         [ +  - ]:      54921 :             const ScPatternAttr* pNewPattern = (const ScPatternAttr*) &pCache->ApplyTo( *pOldPattern, true );
     730         [ +  - ]:      54921 :             ScDocumentPool::CheckRef( *pOldPattern );
     731         [ +  - ]:      54921 :             ScDocumentPool::CheckRef( *pNewPattern );
     732         [ +  + ]:      54921 :             if (pNewPattern != pOldPattern)
     733                 :            :             {
     734                 :      54464 :                 SCROW nY1 = nStart;
     735                 :      54464 :                 SCROW nY2 = pData[nPos].nRow;
     736                 :      54464 :                 nStart = pData[nPos].nRow + 1;
     737                 :            : 
     738 [ +  + ][ +  + ]:      54464 :                 if ( nY1 < nStartRow || nY2 > nEndRow )
     739                 :            :                 {
     740         [ +  + ]:       5122 :                     if (nY1 < nStartRow) nY1=nStartRow;
     741         [ +  + ]:       5122 :                     if (nY2 > nEndRow) nY2=nEndRow;
     742         [ +  - ]:       5122 :                     SetPatternArea( nY1, nY2, pNewPattern, false, pDataArray );
     743                 :       5122 :                     Search( nStart, nPos );
     744                 :            :                 }
     745                 :            :                 else
     746                 :            :                 {
     747                 :            :                     // ensure attributing changes text-width of cell
     748                 :            : 
     749                 :      49342 :                     const SfxItemSet& rNewSet = pNewPattern->GetItemSet();
     750                 :      49342 :                     const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
     751                 :            : 
     752                 :            :                     bool bNumFormatChanged;
     753         [ +  + ]:      49342 :                     if ( ScGlobal::CheckWidthInvalidate( bNumFormatChanged,
     754         [ +  - ]:      49342 :                             rNewSet, rOldSet ) )
     755                 :            :                     {
     756         [ +  + ]:       1022 :                         aAdrStart.SetRow( nPos ? pData[nPos-1].nRow+1 : 0 );
     757                 :       1022 :                         aAdrEnd  .SetRow( pData[nPos].nRow );
     758         [ +  - ]:       1022 :                         pDocument->InvalidateTextWidth( &aAdrStart, &aAdrEnd, bNumFormatChanged );
     759                 :            :                     }
     760                 :            : 
     761 [ +  - ][ +  - ]:      49342 :                     pDocument->GetPool()->Remove(*pData[nPos].pPattern);
     762                 :      49342 :                     pData[nPos].pPattern = pNewPattern;
     763 [ +  - ][ -  + ]:      49342 :                     if (Concat(nPos))
     764                 :          0 :                         Search(nStart, nPos);
     765                 :            :                     else
     766                 :      54464 :                         ++nPos;
     767                 :            :                 }
     768                 :            :             }
     769                 :            :             else
     770                 :            :             {
     771                 :        457 :                 nStart = pData[nPos].nRow + 1;
     772                 :        457 :                 ++nPos;
     773                 :            :             }
     774                 :            :         }
     775                 :            :         while (nStart <= nEndRow);
     776                 :            : 
     777 [ +  - ][ -  + ]:      54867 :         if (pDocument->IsStreamValid(nTab))
     778         [ #  # ]:      54867 :             pDocument->SetStreamValid(nTab, false);
     779                 :            :     }
     780                 :            : 
     781                 :            : #if OSL_DEBUG_LEVEL > 1
     782                 :            :     TestData();
     783                 :            : #endif
     784                 :            : }
     785                 :            : 
     786                 :      24940 : bool ScAttrArray::SetAttrEntries(ScAttrEntry* pNewData, SCSIZE nSize)
     787                 :            : {
     788         [ +  - ]:      24940 :     if (pData)
     789                 :            :     {
     790                 :      24940 :         ScDocumentPool* pDocPool = pDocument->GetPool();
     791         [ +  + ]:      49880 :         for (SCSIZE i=0; i<nCount; i++)
     792                 :      24940 :             pDocPool->Remove(*pData[i].pPattern);
     793                 :            : 
     794         [ +  - ]:      24940 :         delete[] pData;
     795                 :            :     }
     796                 :            : 
     797                 :      24940 :     pData = pNewData;
     798                 :      24940 :     nCount = nLimit = nSize;
     799                 :      24940 :     return true;
     800                 :            : }
     801                 :            : 
     802                 :         46 : void lcl_MergeDeep( SfxItemSet& rMergeSet, const SfxItemSet& rSource )
     803                 :            : {
     804                 :            :     const SfxPoolItem* pNewItem;
     805                 :            :     const SfxPoolItem* pOldItem;
     806         [ +  + ]:       2622 :     for (sal_uInt16 nId=ATTR_PATTERN_START; nId<=ATTR_PATTERN_END; nId++)
     807                 :            :     {
     808                 :            :         //  pMergeSet has no parent
     809         [ +  - ]:       2576 :         SfxItemState eOldState = rMergeSet.GetItemState( nId, false, &pOldItem );
     810                 :            : 
     811         [ +  + ]:       2576 :         if ( eOldState == SFX_ITEM_DEFAULT )
     812                 :            :         {
     813         [ +  - ]:       2282 :             SfxItemState eNewState = rSource.GetItemState( nId, true, &pNewItem );
     814         [ +  + ]:       2282 :             if ( eNewState == SFX_ITEM_SET )
     815                 :            :             {
     816 [ +  - ][ +  - ]:         46 :                 if ( *pNewItem != rMergeSet.GetPool()->GetDefaultItem(nId) )
                 [ +  + ]
     817         [ +  - ]:          2 :                     rMergeSet.InvalidateItem( nId );
     818                 :            :             }
     819                 :            :         }
     820         [ +  - ]:        294 :         else if ( eOldState == SFX_ITEM_SET )               // Item gesetzt
     821                 :            :         {
     822         [ +  - ]:        294 :             SfxItemState eNewState = rSource.GetItemState( nId, true, &pNewItem );
     823         [ +  - ]:        294 :             if ( eNewState == SFX_ITEM_SET )
     824                 :            :             {
     825         [ -  + ]:        294 :                 if ( pNewItem != pOldItem )                 // beide gepuhlt
     826         [ #  # ]:          0 :                     rMergeSet.InvalidateItem( nId );
     827                 :            :             }
     828                 :            :             else            // Default
     829                 :            :             {
     830 [ #  # ][ #  # ]:          0 :                 if ( *pOldItem != rSource.GetPool()->GetDefaultItem(nId) )
                 [ #  # ]
     831         [ #  # ]:          0 :                     rMergeSet.InvalidateItem( nId );
     832                 :            :             }
     833                 :            :         }
     834                 :            :         // Dontcare remains Dontcare
     835                 :            :     }
     836                 :         46 : }
     837                 :            : 
     838                 :            : 
     839                 :      67318 : void ScAttrArray::MergePatternArea( SCROW nStartRow, SCROW nEndRow,
     840                 :            :                                     ScMergePatternState& rState, bool bDeep ) const
     841                 :            : {
     842 [ +  - ][ +  - ]:      67318 :     if (ValidRow(nStartRow) && ValidRow(nEndRow))
                 [ +  - ]
     843                 :            :     {
     844                 :            :         SCSIZE nPos;
     845                 :      67318 :         SCROW nStart=0;
     846         [ +  - ]:      67318 :         if (!Search( nStartRow, nPos ))
     847                 :            :         {
     848                 :            :             OSL_FAIL("Search failure");
     849                 :      67318 :             return;
     850                 :            :         }
     851                 :            : 
     852         [ +  + ]:      67396 :         do
     853                 :            :         {
     854                 :            :             // similar patterns must not be repeated
     855                 :            : 
     856                 :      67396 :             const ScPatternAttr* pPattern = pData[nPos].pPattern;
     857 [ +  + ][ +  + ]:      67396 :             if ( pPattern != rState.pOld1 && pPattern != rState.pOld2 )
     858                 :            :             {
     859                 :       7349 :                 const SfxItemSet& rThisSet = pPattern->GetItemSet();
     860         [ +  + ]:       7349 :                 if (rState.pItemSet)
     861                 :            :                 {
     862         [ +  - ]:         46 :                     if (bDeep)
     863         [ +  - ]:         46 :                         lcl_MergeDeep( *rState.pItemSet, rThisSet );
     864                 :            :                     else
     865         [ #  # ]:          0 :                         rState.pItemSet->MergeValues( rThisSet, false );
     866                 :            :                 }
     867                 :            :                 else
     868                 :            :                 {
     869                 :            :                     // first pattern - copied from parent
     870 [ +  - ][ +  - ]:       7303 :                     rState.pItemSet = new SfxItemSet( *rThisSet.GetPool(), rThisSet.GetRanges() );
     871         [ +  - ]:       7303 :                     rState.pItemSet->Set( rThisSet, bDeep );
     872                 :            :                 }
     873                 :            : 
     874                 :       7349 :                 rState.pOld2 = rState.pOld1;
     875                 :       7349 :                 rState.pOld1 = pPattern;
     876                 :            :             }
     877                 :            : 
     878                 :      67396 :             nStart = pData[nPos].nRow + 1;
     879                 :      67396 :             ++nPos;
     880                 :            :         }
     881                 :            :         while (nStart <= nEndRow);
     882                 :            :     }
     883                 :            : }
     884                 :            : 
     885                 :            : 
     886                 :            : 
     887                 :            : // assemble border
     888                 :            : 
     889                 :       1784 : bool lcl_TestAttr( const SvxBorderLine* pOldLine, const SvxBorderLine* pNewLine,
     890                 :            :                             sal_uInt8& rModified, const SvxBorderLine*& rpNew )
     891                 :            : {
     892         [ -  + ]:       1784 :     if (rModified == SC_LINE_DONTCARE)
     893                 :          0 :         return false;               // don't go again
     894                 :            : 
     895         [ +  + ]:       1784 :     if (rModified == SC_LINE_EMPTY)
     896                 :            :     {
     897                 :        272 :         rModified = SC_LINE_SET;
     898                 :        272 :         rpNew = pNewLine;
     899                 :        272 :         return true;                // initial value
     900                 :            :     }
     901                 :            : 
     902         [ +  - ]:       1512 :     if (pOldLine == pNewLine)
     903                 :            :     {
     904                 :       1512 :         rpNew = pOldLine;
     905                 :       1512 :         return false;
     906                 :            :     }
     907                 :            : 
     908 [ #  # ][ #  # ]:          0 :     if (pOldLine && pNewLine)
     909         [ #  # ]:          0 :         if (*pOldLine == *pNewLine)
     910                 :            :         {
     911                 :          0 :             rpNew = pOldLine;
     912                 :          0 :             return false;
     913                 :            :         }
     914                 :            : 
     915                 :          0 :     rModified = SC_LINE_DONTCARE;
     916                 :          0 :     rpNew = NULL;
     917                 :       1784 :     return true;              // another line -> don't care
     918                 :            : }
     919                 :            : 
     920                 :            : 
     921                 :        446 : void lcl_MergeToFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
     922                 :            :                                 ScLineFlags& rFlags, const ScPatternAttr* pPattern,
     923                 :            :                                 bool bLeft, SCCOL nDistRight, bool bTop, SCROW nDistBottom )
     924                 :            : {
     925                 :            :     // right/bottom border set when connected together
     926         [ +  - ]:        446 :     const ScMergeAttr& rMerge = (const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE);
     927         [ -  + ]:        446 :     if ( rMerge.GetColMerge() == nDistRight + 1 )
     928                 :          0 :         nDistRight = 0;
     929         [ -  + ]:        446 :     if ( rMerge.GetRowMerge() == nDistBottom + 1 )
     930                 :          0 :         nDistBottom = 0;
     931                 :            : 
     932         [ +  - ]:        446 :     const SvxBoxItem* pCellFrame = (SvxBoxItem*) &pPattern->GetItemSet().Get( ATTR_BORDER );
     933                 :        446 :     const SvxBorderLine* pLeftAttr   = pCellFrame->GetLeft();
     934                 :        446 :     const SvxBorderLine* pRightAttr  = pCellFrame->GetRight();
     935                 :        446 :     const SvxBorderLine* pTopAttr    = pCellFrame->GetTop();
     936                 :        446 :     const SvxBorderLine* pBottomAttr = pCellFrame->GetBottom();
     937                 :            :     const SvxBorderLine* pNew;
     938                 :            : 
     939         [ +  + ]:        446 :     if (bTop)
     940                 :            :     {
     941 [ +  - ][ +  + ]:        158 :         if (lcl_TestAttr( pLineOuter->GetTop(), pTopAttr, rFlags.nTop, pNew ))
     942         [ +  - ]:         50 :             pLineOuter->SetLine( pNew, BOX_LINE_TOP );
     943                 :            :     }
     944                 :            :     else
     945                 :            :     {
     946 [ +  - ][ -  + ]:        288 :         if (lcl_TestAttr( pLineInner->GetHori(), pTopAttr, rFlags.nHori, pNew ))
     947         [ #  # ]:          0 :             pLineInner->SetLine( pNew, BOXINFO_LINE_HORI );
     948                 :            :     }
     949                 :            : 
     950         [ +  + ]:        446 :     if (nDistBottom == 0)
     951                 :            :     {
     952 [ +  - ][ +  + ]:        158 :         if (lcl_TestAttr( pLineOuter->GetBottom(), pBottomAttr, rFlags.nBottom, pNew ))
     953         [ +  - ]:         50 :             pLineOuter->SetLine( pNew, BOX_LINE_BOTTOM );
     954                 :            :     }
     955                 :            :     else
     956                 :            :     {
     957 [ +  - ][ +  + ]:        288 :         if (lcl_TestAttr( pLineInner->GetHori(), pBottomAttr, rFlags.nHori, pNew ))
     958         [ +  - ]:         36 :             pLineInner->SetLine( pNew, BOXINFO_LINE_HORI );
     959                 :            :     }
     960                 :            : 
     961         [ +  + ]:        446 :     if (bLeft)
     962                 :            :     {
     963 [ +  - ][ +  + ]:        122 :         if (lcl_TestAttr( pLineOuter->GetLeft(), pLeftAttr, rFlags.nLeft, pNew ))
     964         [ +  - ]:         50 :             pLineOuter->SetLine( pNew, BOX_LINE_LEFT );
     965                 :            :     }
     966                 :            :     else
     967                 :            :     {
     968 [ +  - ][ -  + ]:        324 :         if (lcl_TestAttr( pLineInner->GetVert(), pLeftAttr, rFlags.nVert, pNew ))
     969         [ #  # ]:          0 :             pLineInner->SetLine( pNew, BOXINFO_LINE_VERT );
     970                 :            :     }
     971                 :            : 
     972         [ +  + ]:        446 :     if (nDistRight == 0)
     973                 :            :     {
     974 [ +  - ][ +  + ]:        122 :         if (lcl_TestAttr( pLineOuter->GetRight(), pRightAttr, rFlags.nRight, pNew ))
     975         [ +  - ]:         50 :             pLineOuter->SetLine( pNew, BOX_LINE_RIGHT );
     976                 :            :     }
     977                 :            :     else
     978                 :            :     {
     979 [ +  - ][ +  + ]:        324 :         if (lcl_TestAttr( pLineInner->GetVert(), pRightAttr, rFlags.nVert, pNew ))
     980         [ +  - ]:         36 :             pLineInner->SetLine( pNew, BOXINFO_LINE_VERT );
     981                 :            :     }
     982                 :        446 : }
     983                 :            : 
     984                 :            : 
     985                 :        158 : void ScAttrArray::MergeBlockFrame( SvxBoxItem* pLineOuter, SvxBoxInfoItem* pLineInner,
     986                 :            :                     ScLineFlags& rFlags,
     987                 :            :                     SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight ) const
     988                 :            : {
     989                 :            :     const ScPatternAttr* pPattern;
     990                 :            : 
     991         [ +  + ]:        158 :     if (nStartRow == nEndRow)
     992                 :            :     {
     993                 :         14 :         pPattern = GetPattern( nStartRow );
     994                 :         14 :         lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, true, 0 );
     995                 :            :     }
     996                 :            :     else
     997                 :            :     {
     998                 :        144 :         pPattern = GetPattern( nStartRow );
     999                 :            :         lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, true,
    1000         [ +  - ]:        144 :                             nEndRow-nStartRow );
    1001                 :            : 
    1002                 :            :         SCSIZE nStartIndex;
    1003                 :            :         SCSIZE nEndIndex;
    1004                 :        144 :         Search( nStartRow+1, nStartIndex );
    1005                 :        144 :         Search( nEndRow-1, nEndIndex );
    1006         [ +  + ]:        288 :         for (SCSIZE i=nStartIndex; i<=nEndIndex; i++)
    1007                 :            :         {
    1008                 :        144 :             pPattern = (ScPatternAttr*) pData[i].pPattern;
    1009                 :            :             lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, false,
    1010         [ +  - ]:        144 :                             nEndRow - Min( pData[i].nRow, (SCROW)(nEndRow-1) ) );
    1011                 :            :             // nDistBottom here always > 0
    1012                 :            :         }
    1013                 :            : 
    1014                 :        144 :         pPattern = GetPattern( nEndRow );
    1015         [ +  - ]:        144 :         lcl_MergeToFrame( pLineOuter, pLineInner, rFlags, pPattern, bLeft, nDistRight, false, 0 );
    1016                 :            :     }
    1017                 :        158 : }
    1018                 :            : 
    1019                 :            : //
    1020                 :            : // apply border
    1021                 :            : //
    1022                 :            : 
    1023                 :            : // ApplyFrame - on an entry into the array
    1024                 :            : 
    1025                 :       5202 : bool ScAttrArray::ApplyFrame( const SvxBoxItem*     pBoxItem,
    1026                 :            :                               const SvxBoxInfoItem* pBoxInfoItem,
    1027                 :            :                               SCROW nStartRow, SCROW nEndRow,
    1028                 :            :                               bool bLeft, SCCOL nDistRight, bool bTop, SCROW nDistBottom )
    1029                 :            : {
    1030                 :            :     OSL_ENSURE( pBoxItem && pBoxInfoItem, "Linienattribute fehlen!" );
    1031                 :            : 
    1032                 :       5202 :     const ScPatternAttr* pPattern = GetPattern( nStartRow );
    1033                 :            :     const SvxBoxItem* pOldFrame = (const SvxBoxItem*)
    1034         [ +  - ]:       5202 :                                   &pPattern->GetItemSet().Get( ATTR_BORDER );
    1035                 :            : 
    1036                 :            :     // right/bottom border set when connected together
    1037         [ +  - ]:       5202 :     const ScMergeAttr& rMerge = (const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE);
    1038         [ -  + ]:       5202 :     if ( rMerge.GetColMerge() == nDistRight + 1 )
    1039                 :          0 :         nDistRight = 0;
    1040         [ -  + ]:       5202 :     if ( rMerge.GetRowMerge() == nDistBottom + 1 )
    1041                 :          0 :         nDistBottom = 0;
    1042                 :            : 
    1043         [ +  - ]:       5202 :     SvxBoxItem aNewFrame( *pOldFrame );
    1044                 :            : 
    1045 [ +  + ][ +  + ]:       5202 :     if ( bLeft ? pBoxInfoItem->IsValid(VALID_LEFT) : pBoxInfoItem->IsValid(VALID_VERT) )
    1046                 :            :         aNewFrame.SetLine( bLeft ? pBoxItem->GetLeft() : pBoxInfoItem->GetVert(),
    1047 [ +  - ][ +  - ]:       2574 :             BOX_LINE_LEFT );
    1048 [ +  + ][ +  + ]:       5202 :     if ( (nDistRight==0) ? pBoxInfoItem->IsValid(VALID_RIGHT) : pBoxInfoItem->IsValid(VALID_VERT) )
    1049                 :            :         aNewFrame.SetLine( (nDistRight==0) ? pBoxItem->GetRight() : pBoxInfoItem->GetVert(),
    1050 [ +  - ][ +  - ]:       2577 :             BOX_LINE_RIGHT );
    1051 [ +  + ][ +  + ]:       5202 :     if ( bTop ? pBoxInfoItem->IsValid(VALID_TOP) : pBoxInfoItem->IsValid(VALID_HORI) )
    1052                 :            :         aNewFrame.SetLine( bTop ? pBoxItem->GetTop() : pBoxInfoItem->GetHori(),
    1053 [ +  + ][ +  - ]:       3180 :             BOX_LINE_TOP );
    1054 [ +  + ][ +  + ]:       5202 :     if ( (nDistBottom==0) ? pBoxInfoItem->IsValid(VALID_BOTTOM) : pBoxInfoItem->IsValid(VALID_HORI) )
    1055                 :            :         aNewFrame.SetLine( (nDistBottom==0) ? pBoxItem->GetBottom() : pBoxInfoItem->GetHori(),
    1056 [ +  + ][ +  - ]:       3180 :             BOX_LINE_BOTTOM );
    1057                 :            : 
    1058 [ +  - ][ +  + ]:       5202 :     if (aNewFrame == *pOldFrame)
    1059                 :            :     {
    1060                 :            :         // nothing to do
    1061                 :       1110 :         return false;
    1062                 :            :     }
    1063                 :            :     else
    1064                 :            :     {
    1065 [ +  - ][ +  - ]:       4092 :         SfxItemPoolCache aCache( pDocument->GetPool(), &aNewFrame );
    1066         [ +  - ]:       4092 :         ApplyCacheArea( nStartRow, nEndRow, &aCache );
    1067                 :            : 
    1068         [ +  - ]:       4092 :         return true;
    1069         [ +  - ]:       5202 :     }
    1070                 :            : }
    1071                 :            : 
    1072                 :            : 
    1073                 :       3130 : void ScAttrArray::ApplyBlockFrame( const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner,
    1074                 :            :                             SCROW nStartRow, SCROW nEndRow, bool bLeft, SCCOL nDistRight )
    1075                 :            : {
    1076         [ +  + ]:       3130 :     if (nStartRow == nEndRow)
    1077                 :       1863 :         ApplyFrame( pLineOuter, pLineInner, nStartRow, nEndRow, bLeft, nDistRight, true, 0 );
    1078                 :            :     else
    1079                 :            :     {
    1080                 :            :         ApplyFrame( pLineOuter, pLineInner, nStartRow, nStartRow, bLeft, nDistRight,
    1081                 :       1267 :                         true, nEndRow-nStartRow );
    1082                 :            : 
    1083         [ +  + ]:       1267 :         if ( nEndRow > nStartRow+1 )     // inner part available?
    1084                 :            :         {
    1085                 :            :             SCSIZE nStartIndex;
    1086                 :            :             SCSIZE nEndIndex;
    1087                 :        682 :             Search( nStartRow+1, nStartIndex );
    1088                 :        682 :             Search( nEndRow-1, nEndIndex );
    1089                 :        682 :             SCROW nTmpStart = nStartRow+1;
    1090                 :            :             SCROW nTmpEnd;
    1091         [ +  + ]:       1487 :             for (SCSIZE i=nStartIndex; i<=nEndIndex;)
    1092                 :            :             {
    1093                 :        805 :                 nTmpEnd = Min( (SCROW)(nEndRow-1), (SCROW)(pData[i].nRow) );
    1094                 :            :                 bool bChanged = ApplyFrame( pLineOuter, pLineInner, nTmpStart, nTmpEnd,
    1095         [ +  - ]:        805 :                                             bLeft, nDistRight, false, nEndRow-nTmpEnd );
    1096                 :        805 :                 nTmpStart = nTmpEnd+1;
    1097         [ +  + ]:        805 :                 if (bChanged)
    1098                 :            :                 {
    1099                 :        405 :                     Search(nTmpStart, i);
    1100                 :        405 :                     Search(nEndRow-1, nEndIndex);
    1101                 :            :                 }
    1102                 :            :                 else
    1103                 :        400 :                     i++;
    1104                 :            :             }
    1105                 :            :         }
    1106                 :            : 
    1107                 :       1267 :         ApplyFrame( pLineOuter, pLineInner, nEndRow, nEndRow, bLeft, nDistRight, false, 0 );
    1108                 :            :     }
    1109                 :       3130 : }
    1110                 :            : 
    1111                 :            : 
    1112                 :          0 : long lcl_LineSize( const SvxBorderLine& rLine )
    1113                 :            : {
    1114                 :            :     // only one line -> half width, min. 20
    1115                 :            :     // double line   -> half line spacing + (per min. 20)
    1116                 :            : 
    1117                 :          0 :     long nTotal = 0;
    1118                 :          0 :     sal_uInt16 nWidth = Max( rLine.GetOutWidth(), rLine.GetInWidth() );
    1119                 :          0 :     sal_uInt16 nDist = rLine.GetDistance();
    1120         [ #  # ]:          0 :     if (nDist)
    1121                 :            :     {
    1122                 :            :         OSL_ENSURE( rLine.GetOutWidth() && rLine.GetInWidth(),
    1123                 :            :                         "Line has a distance, but only a width?" );
    1124                 :            : 
    1125         [ #  # ]:          0 :         nTotal += ( nDist > 20 ) ? nDist : 20;
    1126         [ #  # ]:          0 :         nTotal += ( nWidth > 20 ) ? nWidth : 20;
    1127                 :            :     }
    1128         [ #  # ]:          0 :     else if (nWidth)
    1129         [ #  # ]:          0 :         nTotal += ( nWidth > 20 ) ? nWidth  : 20;
    1130                 :            : 
    1131                 :            :         // also halved ?
    1132                 :            : 
    1133                 :          0 :     return nTotal;
    1134                 :            : }
    1135                 :            : 
    1136                 :            : // Test if field contains specific attribute
    1137                 :            : 
    1138                 :    8074579 : bool ScAttrArray::HasAttrib( SCROW nRow1, SCROW nRow2, sal_uInt16 nMask ) const
    1139                 :            : {
    1140                 :            :     SCSIZE nStartIndex;
    1141                 :            :     SCSIZE nEndIndex;
    1142                 :    8074579 :     Search( nRow1, nStartIndex );
    1143                 :    8074579 :     Search( nRow2, nEndIndex );
    1144                 :    8074579 :     bool bFound = false;
    1145                 :            : 
    1146 [ +  + ][ +  + ]:   16163964 :     for (SCSIZE i=nStartIndex; i<=nEndIndex && !bFound; i++)
                 [ +  + ]
    1147                 :            :     {
    1148                 :    8089385 :         const ScPatternAttr* pPattern = pData[i].pPattern;
    1149         [ +  + ]:    8089385 :         if ( nMask & HASATTR_MERGED )
    1150                 :            :         {
    1151                 :            :             const ScMergeAttr* pMerge =
    1152         [ +  - ]:       5537 :                     (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
    1153 [ +  + ][ -  + ]:       5537 :             if ( pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1 )
                 [ +  + ]
    1154                 :         13 :                 bFound = true;
    1155                 :            :         }
    1156         [ +  + ]:    8089385 :         if ( nMask & ( HASATTR_OVERLAPPED | HASATTR_NOTOVERLAPPED | HASATTR_AUTOFILTER ) )
    1157                 :            :         {
    1158                 :            :             const ScMergeFlagAttr* pMergeFlag =
    1159         [ +  - ]:      15892 :                     (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG );
    1160 [ +  - ][ +  + ]:      15892 :             if ( (nMask & HASATTR_OVERLAPPED) && pMergeFlag->IsOverlapped() )
                 [ +  + ]
    1161                 :          3 :                 bFound = true;
    1162 [ -  + ][ #  # ]:      15892 :             if ( (nMask & HASATTR_NOTOVERLAPPED) && !pMergeFlag->IsOverlapped() )
                 [ -  + ]
    1163                 :          0 :                 bFound = true;
    1164 [ +  + ][ +  + ]:      15892 :             if ( (nMask & HASATTR_AUTOFILTER) && pMergeFlag->HasAutoFilter() )
                 [ +  + ]
    1165                 :         26 :                 bFound = true;
    1166                 :            :         }
    1167         [ +  + ]:    8089385 :         if ( nMask & HASATTR_LINES )
    1168                 :            :         {
    1169                 :            :             const SvxBoxItem* pBox =
    1170         [ +  - ]:     104709 :                     (const SvxBoxItem*) &pPattern->GetItem( ATTR_BORDER );
    1171 [ +  + ][ +  - ]:     104709 :             if ( pBox->GetLeft() || pBox->GetRight() || pBox->GetTop() || pBox->GetBottom() )
         [ +  - ][ -  + ]
                 [ +  + ]
    1172                 :          3 :                 bFound = true;
    1173                 :            :         }
    1174         [ +  + ]:    8089385 :         if ( nMask & HASATTR_SHADOW )
    1175                 :            :         {
    1176                 :            :             const SvxShadowItem* pShadow =
    1177         [ +  - ]:     104403 :                     (const SvxShadowItem*) &pPattern->GetItem( ATTR_SHADOW );
    1178         [ -  + ]:     104403 :             if ( pShadow->GetLocation() != SVX_SHADOW_NONE )
    1179                 :          0 :                 bFound = true;
    1180                 :            :         }
    1181         [ +  + ]:    8089385 :         if ( nMask & HASATTR_CONDITIONAL )
    1182                 :            :         {
    1183                 :            :             const SfxUInt32Item* pConditional =
    1184         [ +  - ]:    4863712 :                     (const SfxUInt32Item*) &pPattern->GetItem( ATTR_CONDITIONAL );
    1185         [ +  + ]:    4863712 :             if ( pConditional->GetValue() != 0 )
    1186                 :        903 :                 bFound = true;
    1187                 :            :         }
    1188         [ +  + ]:    8089385 :         if ( nMask & HASATTR_PROTECTED )
    1189                 :            :         {
    1190                 :            :             const ScProtectionAttr* pProtect =
    1191         [ +  - ]:         20 :                     (const ScProtectionAttr*) &pPattern->GetItem( ATTR_PROTECTION );
    1192 [ -  + ][ #  # ]:         20 :             if ( pProtect->GetProtection() || pProtect->GetHideCell() )
                 [ +  - ]
    1193                 :         20 :                 bFound = true;
    1194                 :            :         }
    1195         [ +  + ]:    8089385 :         if ( nMask & HASATTR_ROTATE )
    1196                 :            :         {
    1197                 :            :             const SfxInt32Item* pRotate =
    1198         [ +  - ]:      73356 :                     (const SfxInt32Item*) &pPattern->GetItem( ATTR_ROTATE_VALUE );
    1199                 :            :             // 90 or 270 degrees is former SvxOrientationItem - only look for other values
    1200                 :            :             // (see ScPatternAttr::GetCellOrientation)
    1201                 :      73356 :             sal_Int32 nAngle = pRotate->GetValue();
    1202 [ +  - ][ +  + ]:      73356 :             if ( nAngle != 0 && nAngle != 9000 && nAngle != 27000 )
                 [ +  + ]
    1203                 :        545 :                 bFound = true;
    1204                 :            :         }
    1205         [ +  + ]:    8089385 :         if ( nMask & HASATTR_NEEDHEIGHT )
    1206                 :            :         {
    1207 [ +  - ][ -  + ]:       2531 :             if (pPattern->GetCellOrientation() != SVX_ORIENTATION_STANDARD)
    1208                 :          0 :                 bFound = true;
    1209 [ +  - ][ -  + ]:       2531 :             else if (((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK )).GetValue())
    1210                 :          0 :                 bFound = true;
    1211         [ -  + ]:       2531 :             else if ((SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->
    1212         [ +  - ]:       2531 :                         GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK)
    1213                 :          0 :                 bFound = true;
    1214 [ +  - ][ -  + ]:       2531 :             else if (((const SfxUInt32Item&)pPattern->GetItem( ATTR_CONDITIONAL )).GetValue())
    1215                 :          0 :                 bFound = true;
    1216 [ +  - ][ -  + ]:       2531 :             else if (((const SfxInt32Item&)pPattern->GetItem( ATTR_ROTATE_VALUE )).GetValue())
    1217                 :          0 :                 bFound = true;
    1218                 :            :         }
    1219         [ +  + ]:    8089385 :         if ( nMask & ( HASATTR_SHADOW_RIGHT | HASATTR_SHADOW_DOWN ) )
    1220                 :            :         {
    1221                 :            :             const SvxShadowItem* pShadow =
    1222         [ +  - ]:       1704 :                     (const SvxShadowItem*) &pPattern->GetItem( ATTR_SHADOW );
    1223                 :       1704 :             SvxShadowLocation eLoc = pShadow->GetLocation();
    1224         [ +  + ]:       1704 :             if ( nMask & HASATTR_SHADOW_RIGHT )
    1225 [ +  - ][ -  + ]:        240 :                 if ( eLoc == SVX_SHADOW_TOPRIGHT || eLoc == SVX_SHADOW_BOTTOMRIGHT )
    1226                 :          0 :                     bFound = true;
    1227         [ +  + ]:       1704 :             if ( nMask & HASATTR_SHADOW_DOWN )
    1228 [ +  - ][ -  + ]:       1464 :                 if ( eLoc == SVX_SHADOW_BOTTOMLEFT || eLoc == SVX_SHADOW_BOTTOMRIGHT )
    1229                 :          0 :                     bFound = true;
    1230                 :            :         }
    1231         [ -  + ]:    8089385 :         if ( nMask & HASATTR_RTL )
    1232                 :            :         {
    1233                 :            :             const SvxFrameDirectionItem& rDirection =
    1234         [ #  # ]:          0 :                     (const SvxFrameDirectionItem&) pPattern->GetItem( ATTR_WRITINGDIR );
    1235         [ #  # ]:          0 :             if ( rDirection.GetValue() == FRMDIR_HORI_RIGHT_TOP )
    1236                 :          0 :                 bFound = true;
    1237                 :            :         }
    1238         [ +  + ]:    8089385 :         if ( nMask & HASATTR_RIGHTORCENTER )
    1239                 :            :         {
    1240                 :            :             //  called only if the sheet is LTR, so physical=logical alignment can be assumed
    1241                 :            :             SvxCellHorJustify eHorJust = (SvxCellHorJustify)
    1242         [ +  - ]:    3204952 :                     ((const SvxHorJustifyItem&) pPattern->GetItem( ATTR_HOR_JUSTIFY )).GetValue();
    1243 [ +  + ][ +  + ]:    3204952 :             if ( eHorJust == SVX_HOR_JUSTIFY_RIGHT || eHorJust == SVX_HOR_JUSTIFY_CENTER )
    1244                 :        202 :                 bFound = true;
    1245                 :            :         }
    1246                 :            :     }
    1247                 :            : 
    1248                 :    8074579 :     return bFound;
    1249                 :            : }
    1250                 :            : 
    1251                 :            : // Area around any given summaries expand and adapt any MergeFlag (bRefresh)
    1252                 :       9873 : bool ScAttrArray::ExtendMerge( SCCOL nThisCol, SCROW nStartRow, SCROW nEndRow,
    1253                 :            :                                 SCCOL& rPaintCol, SCROW& rPaintRow,
    1254                 :            :                                 bool bRefresh )
    1255                 :            : {
    1256                 :            :     const ScPatternAttr* pPattern;
    1257                 :            :     const ScMergeAttr* pItem;
    1258                 :            :     SCSIZE nStartIndex;
    1259                 :            :     SCSIZE nEndIndex;
    1260                 :       9873 :     Search( nStartRow, nStartIndex );
    1261                 :       9873 :     Search( nEndRow, nEndIndex );
    1262                 :       9873 :     bool bFound = false;
    1263                 :            : 
    1264         [ +  + ]:      20398 :     for (SCSIZE i=nStartIndex; i<=nEndIndex; i++)
    1265                 :            :     {
    1266                 :      10525 :         pPattern = pData[i].pPattern;
    1267         [ +  - ]:      10525 :         pItem = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
    1268                 :      10525 :         SCsCOL  nCountX = pItem->GetColMerge();
    1269                 :      10525 :         SCsROW  nCountY = pItem->GetRowMerge();
    1270 [ -  + ][ +  + ]:      10525 :         if (nCountX>1 || nCountY>1)
    1271                 :            :         {
    1272         [ +  + ]:         39 :             SCROW nThisRow = (i>0) ? pData[i-1].nRow+1 : 0;
    1273                 :         39 :             SCCOL nMergeEndCol = nThisCol + nCountX - 1;
    1274                 :         39 :             SCROW nMergeEndRow = nThisRow + nCountY - 1;
    1275 [ +  + ][ +  - ]:         39 :             if (nMergeEndCol > rPaintCol && nMergeEndCol <= MAXCOL)
    1276                 :         30 :                 rPaintCol = nMergeEndCol;
    1277 [ +  + ][ +  - ]:         39 :             if (nMergeEndRow > rPaintRow && nMergeEndRow <= MAXROW)
    1278                 :         32 :                 rPaintRow = nMergeEndRow;
    1279                 :         39 :             bFound = true;
    1280                 :            : 
    1281         [ +  + ]:         39 :             if (bRefresh)
    1282                 :            :             {
    1283         [ +  - ]:          3 :                 if ( nMergeEndCol > nThisCol )
    1284                 :          3 :                     pDocument->ApplyFlagsTab( nThisCol+1, nThisRow, nMergeEndCol, pData[i].nRow,
    1285         [ +  - ]:          3 :                                 nTab, SC_MF_HOR );
    1286         [ +  - ]:          3 :                 if ( nMergeEndRow > nThisRow )
    1287                 :            :                     pDocument->ApplyFlagsTab( nThisCol, nThisRow+1, nThisCol, nMergeEndRow,
    1288         [ +  - ]:          3 :                                 nTab, SC_MF_VER );
    1289 [ +  - ][ +  - ]:          3 :                 if ( nMergeEndCol > nThisCol && nMergeEndRow > nThisRow )
    1290                 :            :                     pDocument->ApplyFlagsTab( nThisCol+1, nThisRow+1, nMergeEndCol, nMergeEndRow,
    1291         [ +  - ]:          3 :                                 nTab, SC_MF_HOR | SC_MF_VER );
    1292                 :            : 
    1293                 :          3 :                 Search( nThisRow, i );    // Data changed
    1294                 :          3 :                 Search( nStartRow, nStartIndex );
    1295                 :          3 :                 Search( nEndRow, nEndIndex );
    1296                 :            :             }
    1297                 :            :         }
    1298                 :            :     }
    1299                 :            : 
    1300                 :       9873 :     return bFound;
    1301                 :            : }
    1302                 :            : 
    1303                 :            : 
    1304                 :       8399 : bool ScAttrArray::RemoveAreaMerge(SCROW nStartRow, SCROW nEndRow)
    1305                 :            : {
    1306                 :       8399 :     bool bFound = false;
    1307                 :            :     const ScPatternAttr* pPattern;
    1308                 :            :     const ScMergeAttr* pItem;
    1309                 :            :     SCSIZE nIndex;
    1310                 :            : 
    1311                 :       8399 :     Search( nStartRow, nIndex );
    1312         [ +  + ]:       8399 :     SCROW nThisStart = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
    1313         [ +  + ]:       8399 :     if (nThisStart < nStartRow)
    1314                 :        344 :         nThisStart = nStartRow;
    1315                 :            : 
    1316         [ +  + ]:      19082 :     while ( nThisStart <= nEndRow )
    1317                 :            :     {
    1318                 :      10683 :         SCROW nThisEnd = pData[nIndex].nRow;
    1319         [ +  + ]:      10683 :         if (nThisEnd > nEndRow)
    1320                 :       4860 :             nThisEnd = nEndRow;
    1321                 :            : 
    1322                 :      10683 :         pPattern = pData[nIndex].pPattern;
    1323         [ +  - ]:      10683 :         pItem = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
    1324                 :      10683 :         SCsCOL  nCountX = pItem->GetColMerge();
    1325                 :      10683 :         SCsROW  nCountY = pItem->GetRowMerge();
    1326 [ -  + ][ +  - ]:      10683 :         if (nCountX>1 || nCountY>1)
    1327                 :            :         {
    1328                 :            :             const ScMergeAttr* pAttr = (const ScMergeAttr*)
    1329 [ #  # ][ #  # ]:          0 :                                             &pDocument->GetPool()->GetDefaultItem( ATTR_MERGE );
    1330                 :            :             const ScMergeFlagAttr* pFlagAttr = (const ScMergeFlagAttr*)
    1331 [ #  # ][ #  # ]:          0 :                                             &pDocument->GetPool()->GetDefaultItem( ATTR_MERGE_FLAG );
    1332                 :            : 
    1333                 :            :             OSL_ENSURE( nCountY==1 || nThisStart==nThisEnd, "What's up?" );
    1334                 :            : 
    1335                 :          0 :             SCCOL nThisCol = nCol;
    1336                 :          0 :             SCCOL nMergeEndCol = nThisCol + nCountX - 1;
    1337                 :          0 :             SCROW nMergeEndRow = nThisEnd + nCountY - 1;
    1338                 :            : 
    1339                 :            :             // ApplyAttr for areas
    1340                 :            : 
    1341         [ #  # ]:          0 :             for (SCROW nThisRow = nThisStart; nThisRow <= nThisEnd; nThisRow++)
    1342         [ #  # ]:          0 :                 pDocument->ApplyAttr( nThisCol, nThisRow, nTab, *pAttr );
    1343                 :            : 
    1344 [ #  # ][ #  # ]:          0 :             ScPatternAttr*  pNewPattern = new ScPatternAttr( pDocument->GetPool() );
                 [ #  # ]
    1345                 :          0 :             SfxItemSet*     pSet = &pNewPattern->GetItemSet();
    1346         [ #  # ]:          0 :             pSet->Put( *pFlagAttr );
    1347                 :            :             pDocument->ApplyPatternAreaTab( nThisCol, nThisStart, nMergeEndCol, nMergeEndRow,
    1348         [ #  # ]:          0 :                                                 nTab, *pNewPattern );
    1349 [ #  # ][ #  # ]:          0 :             delete pNewPattern;
    1350                 :            : 
    1351                 :          0 :             Search( nThisEnd, nIndex );    // data changed
    1352                 :            :         }
    1353                 :            : 
    1354                 :      10683 :         ++nIndex;
    1355         [ +  + ]:      10683 :         if ( nIndex < nCount )
    1356                 :       2753 :             nThisStart = pData[nIndex-1].nRow+1;
    1357                 :            :         else
    1358                 :       7930 :             nThisStart = MAXROW+1;   // End
    1359                 :            :     }
    1360                 :            : 
    1361                 :       8399 :     return bFound;
    1362                 :            : }
    1363                 :            : 
    1364                 :            : // Remove field, but leave MergeFlags
    1365                 :            : 
    1366                 :         26 : void ScAttrArray::DeleteAreaSafe(SCROW nStartRow, SCROW nEndRow)
    1367                 :            : {
    1368                 :         26 :     SetPatternAreaSafe( nStartRow, nEndRow, pDocument->GetDefPattern(), true );
    1369                 :         26 : }
    1370                 :            : 
    1371                 :            : 
    1372                 :         26 : void ScAttrArray::SetPatternAreaSafe( SCROW nStartRow, SCROW nEndRow,
    1373                 :            :                         const ScPatternAttr* pWantedPattern, bool bDefault )
    1374                 :            : {
    1375                 :            :     const ScPatternAttr*    pOldPattern;
    1376                 :            :     const ScMergeFlagAttr*  pItem;
    1377                 :            : 
    1378                 :            :     SCSIZE  nIndex;
    1379                 :            :     SCROW   nRow;
    1380                 :            :     SCROW   nThisRow;
    1381                 :         26 :     bool    bFirstUse = true;
    1382                 :            : 
    1383                 :         26 :     Search( nStartRow, nIndex );
    1384         [ +  + ]:         26 :     nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
    1385         [ +  + ]:        242 :     while ( nThisRow <= nEndRow )
    1386                 :            :     {
    1387                 :        216 :         pOldPattern = pData[nIndex].pPattern;
    1388         [ +  - ]:        216 :         if (pOldPattern != pWantedPattern)                          //! else-Zweig ?
    1389                 :            :         {
    1390         [ -  + ]:        216 :             if (nThisRow < nStartRow) nThisRow = nStartRow;
    1391                 :        216 :             nRow = pData[nIndex].nRow;
    1392                 :        216 :             SCROW nAttrRow = Min( (SCROW)nRow, (SCROW)nEndRow );
    1393         [ +  - ]:        216 :             pItem = (const ScMergeFlagAttr*) &pOldPattern->GetItem( ATTR_MERGE_FLAG );
    1394                 :            : 
    1395 [ +  - ][ +  + ]:        216 :             if (pItem->IsOverlapped() || pItem->HasAutoFilter())
                 [ +  + ]
    1396                 :            :             {
    1397                 :            :                 //  default-constructing a ScPatternAttr for DeleteArea doesn't work
    1398                 :            :                 //  because it would have no cell style information.
    1399                 :            :                 //  Instead, the document's GetDefPattern is copied. Since it is passed as
    1400                 :            :                 //  pWantedPattern, no special treatment of default is needed here anymore.
    1401 [ +  - ][ +  - ]:         26 :                 ScPatternAttr*  pNewPattern = new ScPatternAttr( *pWantedPattern );
    1402                 :         26 :                 SfxItemSet*     pSet = &pNewPattern->GetItemSet();
    1403         [ +  - ]:         26 :                 pSet->Put( *pItem );
    1404         [ +  - ]:         26 :                 SetPatternArea( nThisRow, nAttrRow, pNewPattern, true );
    1405 [ +  - ][ +  - ]:         26 :                 delete pNewPattern;
    1406                 :            :             }
    1407                 :            :             else
    1408                 :            :             {
    1409         [ -  + ]:        190 :                 if ( !bDefault )
    1410                 :            :                 {
    1411         [ #  # ]:          0 :                     if (bFirstUse)
    1412                 :          0 :                         bFirstUse = false;
    1413                 :            :                     else
    1414                 :            :                         // it's in the pool
    1415 [ #  # ][ #  # ]:          0 :                         pDocument->GetPool()->Put( *pWantedPattern );
    1416                 :            :                 }
    1417         [ +  - ]:        190 :                 SetPatternArea( nThisRow, nAttrRow, pWantedPattern );
    1418                 :            :             }
    1419                 :            : 
    1420                 :        216 :             Search( nThisRow, nIndex );   // data changed
    1421                 :            :         }
    1422                 :            : 
    1423                 :        216 :         ++nIndex;
    1424                 :        216 :         nThisRow = pData[nIndex-1].nRow+1;
    1425                 :            :     }
    1426                 :         26 : }
    1427                 :            : 
    1428                 :            : 
    1429                 :       1422 : bool ScAttrArray::ApplyFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
    1430                 :            : {
    1431                 :            :     const ScPatternAttr* pOldPattern;
    1432                 :            : 
    1433                 :            :     sal_Int16   nOldValue;
    1434                 :            :     SCSIZE  nIndex;
    1435                 :            :     SCROW   nRow;
    1436                 :            :     SCROW   nThisRow;
    1437                 :       1422 :     bool    bChanged = false;
    1438                 :            : 
    1439                 :       1422 :     Search( nStartRow, nIndex );
    1440         [ +  + ]:       1422 :     nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
    1441         [ +  + ]:       1422 :     if (nThisRow < nStartRow) nThisRow = nStartRow;
    1442                 :            : 
    1443         [ +  + ]:       6457 :     while ( nThisRow <= nEndRow )
    1444                 :            :     {
    1445                 :       5035 :         pOldPattern = pData[nIndex].pPattern;
    1446         [ +  - ]:       5035 :         nOldValue = ((const ScMergeFlagAttr*) &pOldPattern->GetItem( ATTR_MERGE_FLAG ))->GetValue();
    1447         [ +  + ]:       5035 :         if ( (nOldValue | nFlags) != nOldValue )
    1448                 :            :         {
    1449                 :       4933 :             nRow = pData[nIndex].nRow;
    1450                 :       4933 :             SCROW nAttrRow = Min( (SCROW)nRow, (SCROW)nEndRow );
    1451         [ +  - ]:       4933 :             ScPatternAttr aNewPattern(*pOldPattern);
    1452 [ +  - ][ +  - ]:       4933 :             aNewPattern.GetItemSet().Put( ScMergeFlagAttr( nOldValue | nFlags ) );
                 [ +  - ]
    1453         [ +  - ]:       4933 :             SetPatternArea( nThisRow, nAttrRow, &aNewPattern, true );
    1454                 :       4933 :             Search( nThisRow, nIndex );  // data changed
    1455         [ +  - ]:       4933 :             bChanged = true;
    1456                 :            :         }
    1457                 :            : 
    1458                 :       5035 :         ++nIndex;
    1459                 :       5035 :         nThisRow = pData[nIndex-1].nRow+1;
    1460                 :            :     }
    1461                 :            : 
    1462                 :       1422 :     return bChanged;
    1463                 :            : }
    1464                 :            : 
    1465                 :            : 
    1466                 :      41094 : bool ScAttrArray::RemoveFlags( SCROW nStartRow, SCROW nEndRow, sal_Int16 nFlags )
    1467                 :            : {
    1468                 :            :     const ScPatternAttr* pOldPattern;
    1469                 :            : 
    1470                 :            :     sal_Int16   nOldValue;
    1471                 :            :     SCSIZE  nIndex;
    1472                 :            :     SCROW   nRow;
    1473                 :            :     SCROW   nThisRow;
    1474                 :      41094 :     bool    bChanged = false;
    1475                 :            : 
    1476                 :      41094 :     Search( nStartRow, nIndex );
    1477         [ +  + ]:      41094 :     nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
    1478         [ +  + ]:      41094 :     if (nThisRow < nStartRow) nThisRow = nStartRow;
    1479                 :            : 
    1480         [ +  + ]:      82949 :     while ( nThisRow <= nEndRow )
    1481                 :            :     {
    1482                 :      41855 :         pOldPattern = pData[nIndex].pPattern;
    1483         [ +  - ]:      41855 :         nOldValue = ((const ScMergeFlagAttr*) &pOldPattern->GetItem( ATTR_MERGE_FLAG ))->GetValue();
    1484         [ +  + ]:      41855 :         if ( (nOldValue & ~nFlags) != nOldValue )
    1485                 :            :         {
    1486                 :        788 :             nRow = pData[nIndex].nRow;
    1487                 :        788 :             SCROW nAttrRow = Min( (SCROW)nRow, (SCROW)nEndRow );
    1488         [ +  - ]:        788 :             ScPatternAttr aNewPattern(*pOldPattern);
    1489 [ +  - ][ +  - ]:        788 :             aNewPattern.GetItemSet().Put( ScMergeFlagAttr( nOldValue & ~nFlags ) );
                 [ +  - ]
    1490         [ +  - ]:        788 :             SetPatternArea( nThisRow, nAttrRow, &aNewPattern, true );
    1491                 :        788 :             Search( nThisRow, nIndex );  // data changed
    1492         [ +  - ]:        788 :             bChanged = true;
    1493                 :            :         }
    1494                 :            : 
    1495                 :      41855 :         ++nIndex;
    1496                 :      41855 :         nThisRow = pData[nIndex-1].nRow+1;
    1497                 :            :     }
    1498                 :            : 
    1499                 :      41094 :     return bChanged;
    1500                 :            : }
    1501                 :            : 
    1502                 :            : 
    1503                 :          4 : void ScAttrArray::ClearItems( SCROW nStartRow, SCROW nEndRow, const sal_uInt16* pWhich )
    1504                 :            : {
    1505                 :            :     const ScPatternAttr* pOldPattern;
    1506                 :            : 
    1507                 :            :     SCSIZE  nIndex;
    1508                 :            :     SCROW   nRow;
    1509                 :            :     SCROW   nThisRow;
    1510                 :            : 
    1511                 :          4 :     Search( nStartRow, nIndex );
    1512         [ -  + ]:          4 :     nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
    1513         [ -  + ]:          4 :     if (nThisRow < nStartRow) nThisRow = nStartRow;
    1514                 :            : 
    1515         [ +  + ]:          8 :     while ( nThisRow <= nEndRow )
    1516                 :            :     {
    1517                 :          4 :         pOldPattern = pData[nIndex].pPattern;
    1518 [ +  - ][ -  + ]:          4 :         if ( pOldPattern->HasItemsSet( pWhich ) )
    1519                 :            :         {
    1520         [ #  # ]:          0 :             ScPatternAttr aNewPattern(*pOldPattern);
    1521         [ #  # ]:          0 :             aNewPattern.ClearItems( pWhich );
    1522                 :            : 
    1523                 :          0 :             nRow = pData[nIndex].nRow;
    1524                 :          0 :             SCROW nAttrRow = Min( (SCROW)nRow, (SCROW)nEndRow );
    1525         [ #  # ]:          0 :             SetPatternArea( nThisRow, nAttrRow, &aNewPattern, true );
    1526         [ #  # ]:          0 :             Search( nThisRow, nIndex );  // data changed
    1527                 :            :         }
    1528                 :            : 
    1529                 :          4 :         ++nIndex;
    1530                 :          4 :         nThisRow = pData[nIndex-1].nRow+1;
    1531                 :            :     }
    1532                 :          4 : }
    1533                 :            : 
    1534                 :            : 
    1535                 :         34 : void ScAttrArray::ChangeIndent( SCROW nStartRow, SCROW nEndRow, bool bIncrement )
    1536                 :            : {
    1537                 :            :     SCSIZE nIndex;
    1538                 :         34 :     Search( nStartRow, nIndex );
    1539         [ +  + ]:         34 :     SCROW nThisStart = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
    1540         [ +  + ]:         34 :     if (nThisStart < nStartRow) nThisStart = nStartRow;
    1541                 :            : 
    1542         [ +  + ]:         68 :     while ( nThisStart <= nEndRow )
    1543                 :            :     {
    1544                 :         34 :         const ScPatternAttr* pOldPattern = pData[nIndex].pPattern;
    1545                 :         34 :         const SfxItemSet& rOldSet = pOldPattern->GetItemSet();
    1546                 :            :         const SfxPoolItem* pItem;
    1547                 :            : 
    1548         [ +  - ]:         34 :         bool bNeedJust = ( rOldSet.GetItemState( ATTR_HOR_JUSTIFY, false, &pItem ) != SFX_ITEM_SET
    1549 [ +  + ][ -  + ]:         34 :                         || ((const SvxHorJustifyItem*)pItem)->GetValue() != SVX_HOR_JUSTIFY_LEFT );
    1550         [ +  - ]:         34 :         sal_uInt16 nOldValue = ((const SfxUInt16Item&)rOldSet.Get( ATTR_INDENT )).GetValue();
    1551                 :         34 :         sal_uInt16 nNewValue = nOldValue;
    1552         [ +  + ]:         34 :         if ( bIncrement )
    1553                 :            :         {
    1554         [ +  - ]:         17 :             if ( nNewValue < SC_MAX_INDENT )
    1555                 :            :             {
    1556                 :         17 :                 nNewValue += SC_INDENT_STEP;
    1557         [ -  + ]:         17 :                 if ( nNewValue > SC_MAX_INDENT ) nNewValue = SC_MAX_INDENT;
    1558                 :            :             }
    1559                 :            :         }
    1560                 :            :         else
    1561                 :            :         {
    1562         [ +  - ]:         17 :             if ( nNewValue > 0 )
    1563                 :            :             {
    1564         [ -  + ]:         17 :                 if ( nNewValue > SC_INDENT_STEP )
    1565                 :          0 :                     nNewValue -= SC_INDENT_STEP;
    1566                 :            :                 else
    1567                 :         17 :                     nNewValue = 0;
    1568                 :            :             }
    1569                 :            :         }
    1570                 :            : 
    1571 [ +  + ][ +  - ]:         34 :         if ( bNeedJust || nNewValue != nOldValue )
    1572                 :            :         {
    1573                 :         34 :             SCROW nThisEnd = pData[nIndex].nRow;
    1574                 :         34 :             SCROW nAttrRow = Min( nThisEnd, nEndRow );
    1575         [ +  - ]:         34 :             ScPatternAttr aNewPattern(*pOldPattern);
    1576 [ +  - ][ +  - ]:         34 :             aNewPattern.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, nNewValue ) );
                 [ +  - ]
    1577         [ +  + ]:         34 :             if ( bNeedJust )
    1578                 :         17 :                 aNewPattern.GetItemSet().Put(
    1579   [ +  -  +  - ]:         34 :                                 SvxHorJustifyItem( SVX_HOR_JUSTIFY_LEFT, ATTR_HOR_JUSTIFY ) );
                 [ +  - ]
    1580         [ +  - ]:         34 :             SetPatternArea( nThisStart, nAttrRow, &aNewPattern, true );
    1581                 :            : 
    1582                 :         34 :             nThisStart = nThisEnd + 1;
    1583         [ +  - ]:         34 :             Search( nThisStart, nIndex ); // data changed
    1584                 :            :         }
    1585                 :            :         else
    1586                 :            :         {
    1587                 :          0 :             nThisStart = pData[nIndex].nRow + 1;
    1588                 :         34 :             ++nIndex;
    1589                 :            :         }
    1590                 :            :     }
    1591                 :         34 : }
    1592                 :            : 
    1593                 :            : 
    1594                 :          0 : SCsROW ScAttrArray::GetNextUnprotected( SCsROW nRow, bool bUp ) const
    1595                 :            : {
    1596                 :          0 :     long nRet = nRow;
    1597         [ #  # ]:          0 :     if (VALIDROW(nRow))
    1598                 :            :     {
    1599                 :            :         SCSIZE nIndex;
    1600                 :          0 :         Search(nRow, nIndex);
    1601         [ #  # ]:          0 :         while (((const ScProtectionAttr&)pData[nIndex].pPattern->
    1602         [ #  # ]:          0 :                 GetItem(ATTR_PROTECTION)).GetProtection())
    1603                 :            :         {
    1604         [ #  # ]:          0 :             if (bUp)
    1605                 :            :             {
    1606         [ #  # ]:          0 :                 if (nIndex==0)
    1607                 :          0 :                     return -1;   // not found
    1608                 :          0 :                 --nIndex;
    1609                 :          0 :                 nRet = pData[nIndex].nRow;
    1610                 :            :             }
    1611                 :            :             else
    1612                 :            :             {
    1613                 :          0 :                 nRet = pData[nIndex].nRow+1;
    1614                 :          0 :                 ++nIndex;
    1615         [ #  # ]:          0 :                 if (nIndex>=nCount)
    1616                 :          0 :                     return MAXROW+1; // not found
    1617                 :            :             }
    1618                 :            :         }
    1619                 :            :     }
    1620                 :          0 :     return nRet;
    1621                 :            : }
    1622                 :            : 
    1623                 :    5344256 : void ScAttrArray::FindStyleSheet( const SfxStyleSheetBase* pStyleSheet, ScFlatBoolRowSegments& rUsedRows, bool bReset )
    1624                 :            : {
    1625                 :    5344256 :     SCROW nStart = 0;
    1626                 :    5344256 :     SCSIZE nPos = 0;
    1627         [ +  + ]:   10688512 :     while (nPos < nCount)
    1628                 :            :     {
    1629                 :    5344256 :         SCROW nEnd = pData[nPos].nRow;
    1630         [ +  + ]:    5344256 :         if (pData[nPos].pPattern->GetStyleSheet() == pStyleSheet)
    1631                 :            :         {
    1632         [ +  - ]:    3256320 :             rUsedRows.setTrue(nStart, nEnd);
    1633                 :            : 
    1634         [ -  + ]:    3256320 :             if (bReset)
    1635                 :            :             {
    1636 [ #  # ][ #  # ]:          0 :                 ScPatternAttr* pNewPattern = new ScPatternAttr(*pData[nPos].pPattern);
    1637 [ #  # ][ #  # ]:          0 :                 pDocument->GetPool()->Remove(*pData[nPos].pPattern);
    1638                 :            :                 pNewPattern->SetStyleSheet( (ScStyleSheet*)
    1639         [ #  # ]:          0 :                     pDocument->GetStyleSheetPool()->
    1640         [ #  # ]:          0 :                         Find( ScGlobal::GetRscString(STR_STYLENAME_STANDARD),
    1641                 :            :                               SFX_STYLE_FAMILY_PARA,
    1642 [ #  # ][ #  # ]:          0 :                               SFXSTYLEBIT_AUTO | SCSTYLEBIT_STANDARD ) );
    1643                 :          0 :                 pData[nPos].pPattern = (const ScPatternAttr*)
    1644 [ #  # ][ #  # ]:          0 :                                             &pDocument->GetPool()->Put(*pNewPattern);
    1645 [ #  # ][ #  # ]:          0 :                 delete pNewPattern;
    1646                 :            : 
    1647 [ #  # ][ #  # ]:          0 :                 if (Concat(nPos))
    1648                 :            :                 {
    1649                 :          0 :                     Search(nStart, nPos);
    1650                 :          0 :                     --nPos;   // because ++ at end
    1651                 :            :                 }
    1652                 :            :             }
    1653                 :            :         }
    1654                 :    5344256 :         nStart = nEnd + 1;
    1655                 :    5344256 :         ++nPos;
    1656                 :            :     }
    1657                 :    5344256 : }
    1658                 :            : 
    1659                 :            : 
    1660                 :          0 : bool ScAttrArray::IsStyleSheetUsed( const ScStyleSheet& rStyle,
    1661                 :            :         bool bGatherAllStyles ) const
    1662                 :            : {
    1663                 :          0 :     bool    bIsUsed = false;
    1664                 :          0 :     SCSIZE  nPos    = 0;
    1665                 :            : 
    1666         [ #  # ]:          0 :     while ( nPos < nCount )
    1667                 :            :     {
    1668                 :          0 :         const ScStyleSheet* pStyle = pData[nPos].pPattern->GetStyleSheet();
    1669         [ #  # ]:          0 :         if ( pStyle )
    1670                 :            :         {
    1671                 :          0 :             pStyle->SetUsage( ScStyleSheet::USED );
    1672         [ #  # ]:          0 :             if ( pStyle == &rStyle )
    1673                 :            :             {
    1674         [ #  # ]:          0 :                 if ( !bGatherAllStyles )
    1675                 :          0 :                     return true;
    1676                 :          0 :                 bIsUsed = true;
    1677                 :            :             }
    1678                 :            :         }
    1679                 :          0 :         nPos++;
    1680                 :            :     }
    1681                 :            : 
    1682                 :          0 :     return bIsUsed;
    1683                 :            : }
    1684                 :            : 
    1685                 :            : 
    1686                 :          7 : bool ScAttrArray::IsEmpty() const
    1687                 :            : {
    1688         [ +  - ]:          7 :     if (nCount == 1)
    1689                 :            :     {
    1690         [ -  + ]:          7 :         if ( pData[0].pPattern != pDocument->GetDefPattern() )
    1691                 :          0 :             return false;
    1692                 :            :         else
    1693                 :          7 :             return true;
    1694                 :            :     }
    1695                 :            :     else
    1696                 :          7 :         return false;
    1697                 :            : }
    1698                 :            : 
    1699                 :            : 
    1700                 :     893952 : bool ScAttrArray::GetFirstVisibleAttr( SCROW& rFirstRow ) const
    1701                 :            : {
    1702                 :            :     OSL_ENSURE( nCount, "nCount == 0" );
    1703                 :            : 
    1704                 :     893952 :     bool bFound = false;
    1705                 :     893952 :     SCSIZE nStart = 0;
    1706                 :            : 
    1707                 :            :     // Skip first entry if more than 1 row.
    1708                 :            :     // Entries at the end are not skipped, GetFirstVisibleAttr may be larger than GetLastVisibleAttr.
    1709                 :            : 
    1710                 :     893952 :     SCSIZE nVisStart = 1;
    1711 [ +  + ][ +  + ]:     894156 :     while ( nVisStart < nCount && pData[nVisStart].pPattern->IsVisibleEqual(*pData[nVisStart-1].pPattern) )
                 [ +  + ]
    1712                 :        204 :         ++nVisStart;
    1713 [ +  + ][ +  + ]:     893952 :     if ( nVisStart >= nCount || pData[nVisStart-1].nRow > 0 )   // more than 1 row?
    1714                 :     893946 :         nStart = nVisStart;
    1715                 :            : 
    1716 [ +  + ][ +  + ]:     894048 :     while ( nStart < nCount && !bFound )
                 [ +  + ]
    1717                 :            :     {
    1718         [ +  + ]:         96 :         if ( pData[nStart].pPattern->IsVisible() )
    1719                 :            :         {
    1720         [ +  - ]:         90 :             rFirstRow = nStart ? ( pData[nStart-1].nRow + 1 ) : 0;
    1721                 :         90 :             bFound = true;
    1722                 :            :         }
    1723                 :            :         else
    1724                 :          6 :             ++nStart;
    1725                 :            :     }
    1726                 :            : 
    1727                 :     893952 :     return bFound;
    1728                 :            : }
    1729                 :            : 
    1730                 :            : // size (rows) of a range of attributes after cell content where the search is stopped
    1731                 :            : // (more than a default page size, 2*42 because it's as good as any number)
    1732                 :            : 
    1733                 :            : const SCROW SC_VISATTR_STOP = 84;
    1734                 :            : 
    1735                 :    1333980 : bool ScAttrArray::GetLastVisibleAttr( SCROW& rLastRow, SCROW nLastData, bool bFullFormattedArea ) const
    1736                 :            : {
    1737                 :            :     OSL_ENSURE( nCount, "nCount == 0" );
    1738                 :            : 
    1739                 :            :     //  #i30830# changed behavior:
    1740                 :            :     //  ignore all attributes starting with the first run of SC_VISATTR_STOP equal rows
    1741                 :            :     //  below the last content cell
    1742                 :            : 
    1743         [ -  + ]:    1333980 :     if ( nLastData == MAXROW )
    1744                 :            :     {
    1745                 :          0 :         rLastRow = MAXROW;      // can't look for attributes below MAXROW
    1746                 :          0 :         return true;
    1747                 :            :     }
    1748                 :            : 
    1749                 :            :     // Quick check: last data row in or immediately preceding a run that is the
    1750                 :            :     // last attribution down to the end, e.g. default style or column style.
    1751                 :    1333980 :     SCSIZE nPos = nCount - 1;
    1752         [ +  + ]:    1333980 :     SCROW nStartRow = (nPos ? pData[nPos-1].nRow + 1 : 0);
    1753         [ +  + ]:    1333980 :     if (nStartRow <= nLastData + 1)
    1754                 :            :     {
    1755 [ -  + ][ #  # ]:    1333920 :         if (bFullFormattedArea && pData[nPos].pPattern->IsVisible())
         [ #  # ][ -  + ]
    1756                 :            :         {
    1757                 :          0 :             rLastRow = pData[nPos].nRow;
    1758                 :          0 :             return true;
    1759                 :            :         }
    1760                 :            :         else
    1761                 :            :         {
    1762                 :            :             // Ignore here a few rows if data happens to end within
    1763                 :            :             // SC_VISATTR_STOP rows before MAXROW.
    1764                 :    1333920 :             rLastRow = nLastData;
    1765                 :    1333920 :             return false;
    1766                 :            :         }
    1767                 :            :     }
    1768                 :            : 
    1769                 :            :     // Find a run below last data row.
    1770                 :         60 :     bool bFound = false;
    1771                 :         60 :     Search( nLastData, nPos );
    1772         [ +  - ]:        140 :     while ( nPos < nCount )
    1773                 :            :     {
    1774                 :            :         // find range of visually equal formats
    1775                 :        140 :         SCSIZE nEndPos = nPos;
    1776 [ +  + ][ +  + ]:        312 :         while ( nEndPos < nCount-1 &&
                 [ +  + ]
    1777         [ +  - ]:        126 :                 pData[nEndPos].pPattern->IsVisibleEqual( *pData[nEndPos+1].pPattern))
    1778                 :         46 :             ++nEndPos;
    1779         [ +  + ]:        140 :         SCROW nAttrStartRow = ( nPos > 0 ) ? ( pData[nPos-1].nRow + 1 ) : 0;
    1780         [ +  + ]:        140 :         if ( nAttrStartRow <= nLastData )
    1781                 :         60 :             nAttrStartRow = nLastData + 1;
    1782                 :        140 :         SCROW nAttrSize = pData[nEndPos].nRow + 1 - nAttrStartRow;
    1783 [ +  + ][ +  - ]:        140 :         if ( nAttrSize >= SC_VISATTR_STOP && !bFullFormattedArea )
    1784                 :         60 :             break;  // while, ignore this range and below
    1785 [ +  - ][ +  - ]:         80 :         else if ( pData[nEndPos].pPattern->IsVisible() )
    1786                 :            :         {
    1787                 :         80 :             rLastRow = pData[nEndPos].nRow;
    1788                 :         80 :             bFound = true;
    1789                 :            :         }
    1790                 :         80 :         nPos = nEndPos + 1;
    1791                 :            :     }
    1792                 :            : 
    1793                 :    1333980 :     return bFound;
    1794                 :            : }
    1795                 :            : 
    1796                 :            : 
    1797                 :          0 : bool ScAttrArray::HasVisibleAttrIn( SCROW nStartRow, SCROW nEndRow ) const
    1798                 :            : {
    1799                 :            :     SCSIZE nIndex;
    1800                 :          0 :     Search( nStartRow, nIndex );
    1801                 :          0 :     SCROW nThisStart = nStartRow;
    1802                 :          0 :     bool bFound = false;
    1803 [ #  # ][ #  # ]:          0 :     while ( nIndex < nCount && nThisStart <= nEndRow && !bFound )
         [ #  # ][ #  # ]
    1804                 :            :     {
    1805 [ #  # ][ #  # ]:          0 :         if ( pData[nIndex].pPattern->IsVisible() )
    1806                 :          0 :             bFound = true;
    1807                 :            : 
    1808                 :          0 :         nThisStart = pData[nIndex].nRow + 1;
    1809                 :          0 :         ++nIndex;
    1810                 :            :     }
    1811                 :            : 
    1812                 :          0 :     return bFound;
    1813                 :            : }
    1814                 :            : 
    1815                 :            : 
    1816                 :         12 : bool ScAttrArray::IsVisibleEqual( const ScAttrArray& rOther,
    1817                 :            :                                     SCROW nStartRow, SCROW nEndRow ) const
    1818                 :            : {
    1819                 :         12 :     bool bEqual = true;
    1820                 :         12 :     SCSIZE nThisPos = 0;
    1821                 :         12 :     SCSIZE nOtherPos = 0;
    1822         [ -  + ]:         12 :     if ( nStartRow > 0 )
    1823                 :            :     {
    1824                 :          0 :         Search( nStartRow, nThisPos );
    1825                 :          0 :         rOther.Search( nStartRow, nOtherPos );
    1826                 :            :     }
    1827                 :            : 
    1828 [ +  - ][ +  - ]:         48 :     while ( nThisPos<nCount && nOtherPos<rOther.nCount && bEqual )
         [ +  + ][ +  + ]
    1829                 :            :     {
    1830                 :         36 :         SCROW nThisRow = pData[nThisPos].nRow;
    1831                 :         36 :         SCROW nOtherRow = rOther.pData[nOtherPos].nRow;
    1832                 :         36 :         const ScPatternAttr* pThisPattern = pData[nThisPos].pPattern;
    1833                 :         36 :         const ScPatternAttr* pOtherPattern = rOther.pData[nOtherPos].pPattern;
    1834                 :            :         bEqual = ( pThisPattern == pOtherPattern ||
    1835 [ +  + ][ +  - ]:         36 :                     pThisPattern->IsVisibleEqual(*pOtherPattern) );
                 [ +  + ]
    1836                 :            : 
    1837         [ +  + ]:         36 :         if ( nThisRow >= nOtherRow )
    1838                 :            :         {
    1839         [ -  + ]:         30 :             if ( nOtherRow >= nEndRow ) break;
    1840                 :         30 :             ++nOtherPos;
    1841                 :            :         }
    1842         [ +  - ]:         36 :         if ( nThisRow <= nOtherRow )
    1843                 :            :         {
    1844         [ -  + ]:         36 :             if ( nThisRow >= nEndRow ) break;
    1845                 :         36 :             ++nThisPos;
    1846                 :            :         }
    1847                 :            :     }
    1848                 :            : 
    1849                 :         12 :     return bEqual;
    1850                 :            : }
    1851                 :            : 
    1852                 :            : 
    1853                 :      14340 : bool ScAttrArray::IsAllEqual( const ScAttrArray& rOther, SCROW nStartRow, SCROW nEndRow ) const
    1854                 :            : {
    1855                 :            :     // summarised with IsVisibleEqual
    1856                 :            : 
    1857                 :      14340 :     bool bEqual = true;
    1858                 :      14340 :     SCSIZE nThisPos = 0;
    1859                 :      14340 :     SCSIZE nOtherPos = 0;
    1860         [ -  + ]:      14340 :     if ( nStartRow > 0 )
    1861                 :            :     {
    1862                 :          0 :         Search( nStartRow, nThisPos );
    1863                 :          0 :         rOther.Search( nStartRow, nOtherPos );
    1864                 :            :     }
    1865                 :            : 
    1866 [ +  - ][ +  - ]:      14350 :     while ( nThisPos<nCount && nOtherPos<rOther.nCount && bEqual )
         [ +  + ][ +  + ]
    1867                 :            :     {
    1868                 :      14342 :         SCROW nThisRow = pData[nThisPos].nRow;
    1869                 :      14342 :         SCROW nOtherRow = rOther.pData[nOtherPos].nRow;
    1870                 :      14342 :         const ScPatternAttr* pThisPattern = pData[nThisPos].pPattern;
    1871                 :      14342 :         const ScPatternAttr* pOtherPattern = rOther.pData[nOtherPos].pPattern;
    1872                 :      14342 :         bEqual = ( pThisPattern == pOtherPattern );
    1873                 :            : 
    1874         [ +  + ]:      14342 :         if ( nThisRow >= nOtherRow )
    1875                 :            :         {
    1876         [ +  + ]:      14334 :             if ( nOtherRow >= nEndRow ) break;
    1877                 :          2 :             ++nOtherPos;
    1878                 :            :         }
    1879         [ +  - ]:         10 :         if ( nThisRow <= nOtherRow )
    1880                 :            :         {
    1881         [ -  + ]:         10 :             if ( nThisRow >= nEndRow ) break;
    1882                 :         10 :             ++nThisPos;
    1883                 :            :         }
    1884                 :            :     }
    1885                 :            : 
    1886                 :      14340 :     return bEqual;
    1887                 :            : }
    1888                 :            : 
    1889                 :            : 
    1890                 :          0 : bool ScAttrArray::TestInsertCol( SCROW nStartRow, SCROW nEndRow) const
    1891                 :            : {
    1892                 :            :     // Horizontal aggregate are not allowed to be moved out; if whole summary,
    1893                 :            :     // here is not recognized
    1894                 :            : 
    1895                 :          0 :     bool bTest = true;
    1896         [ #  # ]:          0 :     if (!IsEmpty())
    1897                 :            :     {
    1898                 :          0 :         SCSIZE nIndex = 0;
    1899         [ #  # ]:          0 :         if ( nStartRow > 0 )
    1900                 :          0 :             Search( nStartRow, nIndex );
    1901                 :            : 
    1902         [ #  # ]:          0 :         for ( ; nIndex < nCount; nIndex++ )
    1903                 :            :         {
    1904         [ #  # ]:          0 :             if ( ((const ScMergeFlagAttr&)pData[nIndex].pPattern->
    1905         [ #  # ]:          0 :                         GetItem(ATTR_MERGE_FLAG)).IsHorOverlapped() )
    1906                 :            :             {
    1907                 :          0 :                 bTest = false;  // may not be pushed out
    1908                 :          0 :                 break;
    1909                 :            :             }
    1910         [ #  # ]:          0 :             if ( pData[nIndex].nRow >= nEndRow ) // end of range
    1911                 :          0 :                 break;
    1912                 :            :         }
    1913                 :            :     }
    1914                 :          0 :     return bTest;
    1915                 :            : }
    1916                 :            : 
    1917                 :            : 
    1918                 :      18735 : bool ScAttrArray::TestInsertRow( SCSIZE nSize ) const
    1919                 :            : {
    1920                 :            :     // if 1st row pushed out is vertically overlapped, summary would be broken
    1921                 :            : 
    1922         [ +  - ]:      18735 :     if (pData)
    1923                 :            :     {
    1924                 :            :         // MAXROW + 1 - nSize   = 1st row pushed out
    1925                 :            : 
    1926                 :      18735 :         SCSIZE nFirstLost = nCount-1;
    1927 [ +  + ][ -  + ]:      18735 :         while ( nFirstLost && pData[nFirstLost-1].nRow >= sal::static_int_cast<SCROW>(MAXROW + 1 - nSize) )
                 [ -  + ]
    1928                 :          0 :             --nFirstLost;
    1929                 :            : 
    1930         [ -  + ]:      18735 :         if ( ((const ScMergeFlagAttr&)pData[nFirstLost].pPattern->
    1931                 :      18735 :                             GetItem(ATTR_MERGE_FLAG)).IsVerOverlapped() )
    1932                 :          0 :             return false;
    1933                 :            :     }
    1934                 :            : 
    1935                 :      18735 :     return true;
    1936                 :            : }
    1937                 :            : 
    1938                 :            : 
    1939                 :      18735 : void ScAttrArray::InsertRow( SCROW nStartRow, SCSIZE nSize )
    1940                 :            : {
    1941         [ +  - ]:      18735 :     if (!pData)
    1942                 :      18735 :         return;
    1943                 :            : 
    1944         [ +  + ]:      18735 :     SCROW nSearch = nStartRow > 0 ? nStartRow - 1 : 0;  // expand predecessor
    1945                 :            :     SCSIZE nIndex;
    1946                 :      18735 :     Search( nSearch, nIndex );
    1947                 :            : 
    1948                 :            :     // set ScMergeAttr may not be extended (so behind delete again)
    1949                 :            : 
    1950         [ +  - ]:      18735 :     bool bDoMerge = ((const ScMergeAttr&) pData[nIndex].pPattern->GetItem(ATTR_MERGE)).IsMerged();
    1951                 :            : 
    1952                 :      18735 :     SCSIZE nRemove = 0;
    1953                 :            :     SCSIZE i;
    1954         [ +  + ]:      18749 :     for (i = nIndex; i < nCount-1; i++)
    1955                 :            :     {
    1956                 :         14 :         SCROW nNew = pData[i].nRow + nSize;
    1957         [ -  + ]:         14 :         if ( nNew >= MAXROW )    // at end?
    1958                 :            :         {
    1959                 :          0 :             nNew = MAXROW;
    1960         [ #  # ]:          0 :             if (!nRemove)
    1961                 :          0 :                 nRemove = i+1;  // remove the following?
    1962                 :            :         }
    1963                 :         14 :         pData[i].nRow = nNew;
    1964                 :            :     }
    1965                 :            : 
    1966                 :            :     // Remove entries at end ?
    1967                 :            : 
    1968 [ -  + ][ #  # ]:      18735 :     if (nRemove && nRemove < nCount)
    1969         [ #  # ]:          0 :         DeleteRange( nRemove, nCount-1 );
    1970                 :            : 
    1971         [ -  + ]:      18735 :     if (bDoMerge)   // extensively repair (again) ScMergeAttr
    1972                 :            :     {
    1973                 :            :             //  ApplyAttr for areas
    1974                 :            : 
    1975 [ #  # ][ #  # ]:          0 :         const SfxPoolItem& rDef = pDocument->GetPool()->GetDefaultItem( ATTR_MERGE );
    1976         [ #  # ]:          0 :         for (SCSIZE nAdd=0; nAdd<nSize; nAdd++)
    1977         [ #  # ]:          0 :             pDocument->ApplyAttr( nCol, nStartRow+nAdd, nTab, rDef );
    1978                 :            : 
    1979                 :            :         // reply inserts in this area not summarized
    1980                 :            :     }
    1981                 :            : 
    1982                 :            :     // Don't duplicate the merge flags in the inserted row.
    1983                 :            :     // #i108488# SC_MF_SCENARIO has to be allowed.
    1984         [ +  - ]:      18735 :     RemoveFlags( nStartRow, nStartRow+nSize-1, SC_MF_HOR | SC_MF_VER | SC_MF_AUTO | SC_MF_BUTTON );
    1985                 :            : }
    1986                 :            : 
    1987                 :            : 
    1988                 :      10240 : void ScAttrArray::DeleteRow( SCROW nStartRow, SCSIZE nSize )
    1989                 :            : {
    1990         [ +  - ]:      10240 :     if (pData)
    1991                 :            :     {
    1992                 :      10240 :         bool bFirst=true;
    1993                 :      10240 :         SCSIZE nStartIndex = 0;
    1994                 :      10240 :         SCSIZE nEndIndex = 0;
    1995                 :            :         SCSIZE i;
    1996                 :            : 
    1997         [ +  + ]:      10248 :         for ( i = 0; i < nCount-1; i++)
    1998 [ +  + ][ +  + ]:          8 :             if (pData[i].nRow >= nStartRow && pData[i].nRow <= sal::static_int_cast<SCROW>(nStartRow+nSize-1))
                 [ +  + ]
    1999                 :            :             {
    2000         [ +  - ]:          2 :                 if (bFirst)
    2001                 :            :                 {
    2002                 :          2 :                     nStartIndex = i;
    2003                 :          2 :                     bFirst = false;
    2004                 :            :                 }
    2005                 :          2 :                 nEndIndex = i;
    2006                 :            :             }
    2007         [ +  + ]:      10240 :         if (!bFirst)
    2008                 :            :         {
    2009                 :            :             SCROW nStart;
    2010         [ -  + ]:          2 :             if (nStartIndex==0)
    2011                 :          0 :                 nStart = 0;
    2012                 :            :             else
    2013                 :          2 :                 nStart = pData[nStartIndex-1].nRow + 1;
    2014                 :            : 
    2015         [ -  + ]:          2 :             if (nStart < nStartRow)
    2016                 :            :             {
    2017                 :          0 :                 pData[nStartIndex].nRow = nStartRow - 1;
    2018                 :          0 :                 ++nStartIndex;
    2019                 :            :             }
    2020         [ +  - ]:          2 :             if (nEndIndex >= nStartIndex)
    2021                 :            :             {
    2022                 :          2 :                 DeleteRange( nStartIndex, nEndIndex );
    2023         [ +  - ]:          2 :                 if (nStartIndex > 0)
    2024         [ +  - ]:          2 :                     if ( pData[nStartIndex-1].pPattern == pData[nStartIndex].pPattern )
    2025                 :          2 :                         DeleteRange( nStartIndex-1, nStartIndex-1 );
    2026                 :            :             }
    2027                 :            :         }
    2028         [ +  + ]:      10244 :         for (i = 0; i < nCount-1; i++)
    2029         [ +  + ]:          4 :             if (pData[i].nRow >= nStartRow)
    2030                 :          3 :                 pData[i].nRow -= nSize;
    2031                 :            : 
    2032                 :            :         // Below does not follow the pattern to detect pressure ranges;
    2033                 :            :         // instead, only remove merge flags.
    2034                 :      10240 :         RemoveFlags( MAXROW-nSize+1, MAXROW, SC_MF_HOR | SC_MF_VER | SC_MF_AUTO );
    2035                 :            :     }
    2036                 :      10240 : }
    2037                 :            : 
    2038                 :            : 
    2039                 :          4 : void ScAttrArray::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex )
    2040                 :            : {
    2041                 :          4 :     ScDocumentPool* pDocPool = pDocument->GetPool();
    2042         [ +  + ]:          8 :     for (SCSIZE i = nStartIndex; i <= nEndIndex; i++)
    2043                 :          4 :         pDocPool->Remove(*pData[i].pPattern);
    2044                 :            : 
    2045                 :          4 :     memmove( &pData[nStartIndex], &pData[nEndIndex + 1], (nCount - nEndIndex - 1) * sizeof(ScAttrEntry) );
    2046                 :          4 :     nCount -= nEndIndex-nStartIndex+1;
    2047                 :          4 : }
    2048                 :            : 
    2049                 :            : 
    2050                 :       8399 : void ScAttrArray::DeleteArea(SCROW nStartRow, SCROW nEndRow)
    2051                 :            : {
    2052                 :       8399 :     RemoveAreaMerge( nStartRow, nEndRow );  // remove from combined flags
    2053                 :            : 
    2054         [ +  + ]:       8399 :     if ( !HasAttrib( nStartRow, nEndRow, HASATTR_OVERLAPPED | HASATTR_AUTOFILTER) )
    2055                 :       8373 :         SetPatternArea( nStartRow, nEndRow, pDocument->GetDefPattern() );
    2056                 :            :     else
    2057                 :         26 :         DeleteAreaSafe( nStartRow, nEndRow );  // leave merge flags
    2058                 :       8399 : }
    2059                 :            : 
    2060                 :            : 
    2061                 :          2 : void ScAttrArray::DeleteHardAttr(SCROW nStartRow, SCROW nEndRow)
    2062                 :            : {
    2063         [ +  - ]:          2 :     const ScPatternAttr* pDefPattern = pDocument->GetDefPattern();
    2064                 :            :     const ScPatternAttr* pOldPattern;
    2065                 :            : 
    2066                 :            :     SCSIZE  nIndex;
    2067                 :            :     SCROW   nRow;
    2068                 :            :     SCROW   nThisRow;
    2069                 :            : 
    2070                 :          2 :     Search( nStartRow, nIndex );
    2071         [ +  - ]:          2 :     nThisRow = (nIndex>0) ? pData[nIndex-1].nRow+1 : 0;
    2072         [ -  + ]:          2 :     if (nThisRow < nStartRow) nThisRow = nStartRow;
    2073                 :            : 
    2074         [ +  + ]:          4 :     while ( nThisRow <= nEndRow )
    2075                 :            :     {
    2076                 :          2 :         pOldPattern = pData[nIndex].pPattern;
    2077                 :            : 
    2078         [ +  - ]:          2 :         if ( pOldPattern->GetItemSet().Count() )  // hard attributes ?
    2079                 :            :         {
    2080                 :          2 :             nRow = pData[nIndex].nRow;
    2081                 :          2 :             SCROW nAttrRow = Min( (SCROW)nRow, (SCROW)nEndRow );
    2082                 :            : 
    2083         [ +  - ]:          2 :             ScPatternAttr aNewPattern(*pOldPattern);
    2084                 :          2 :             SfxItemSet& rSet = aNewPattern.GetItemSet();
    2085         [ +  + ]:        114 :             for (sal_uInt16 nId = ATTR_PATTERN_START; nId <= ATTR_PATTERN_END; nId++)
    2086 [ +  + ][ +  + ]:        112 :                 if (nId != ATTR_MERGE && nId != ATTR_MERGE_FLAG)
    2087         [ +  - ]:        108 :                     rSet.ClearItem(nId);
    2088                 :            : 
    2089 [ +  - ][ +  - ]:          2 :             if ( aNewPattern == *pDefPattern )
    2090         [ +  - ]:          2 :                 SetPatternArea( nThisRow, nAttrRow, pDefPattern, false );
    2091                 :            :             else
    2092         [ #  # ]:          0 :                 SetPatternArea( nThisRow, nAttrRow, &aNewPattern, true );
    2093                 :            : 
    2094         [ +  - ]:          2 :             Search( nThisRow, nIndex );  // data changed
    2095                 :            :         }
    2096                 :            : 
    2097                 :          2 :         ++nIndex;
    2098                 :          2 :         nThisRow = pData[nIndex-1].nRow+1;
    2099                 :            :     }
    2100                 :          2 : }
    2101                 :            : 
    2102                 :            : 
    2103                 :            : // move within a document
    2104                 :            : 
    2105                 :       3066 : void ScAttrArray::MoveTo(SCROW nStartRow, SCROW nEndRow, ScAttrArray& rAttrArray)
    2106                 :            : {
    2107                 :       3066 :     SCROW nStart = nStartRow;
    2108         [ +  + ]:       6132 :     for (SCSIZE i = 0; i < nCount; i++)
    2109                 :            :     {
    2110 [ +  - ][ -  + ]:       3066 :         if ((pData[i].nRow >= nStartRow) && ((i==0) ? true : pData[i-1].nRow < nEndRow))
                 [ #  # ]
    2111                 :            :         {
    2112                 :            :             // copy (bPutToPool=TRUE)
    2113                 :       3066 :             rAttrArray.SetPatternArea( nStart, Min( (SCROW)pData[i].nRow, (SCROW)nEndRow ),
    2114                 :       3066 :                                         pData[i].pPattern, true );
    2115                 :            :         }
    2116                 :       3066 :         nStart = Max( (SCROW)nStart, (SCROW)(pData[i].nRow + 1) );
    2117                 :            :     }
    2118                 :       3066 :     DeleteArea(nStartRow, nEndRow);
    2119                 :       3066 : }
    2120                 :            : 
    2121                 :            : 
    2122                 :            : // copy between documents (Clipboard)
    2123                 :            : 
    2124                 :      52444 : void ScAttrArray::CopyArea( SCROW nStartRow, SCROW nEndRow, long nDy, ScAttrArray& rAttrArray,
    2125                 :            :                                 sal_Int16 nStripFlags )
    2126                 :            : {
    2127                 :      52444 :     nStartRow -= nDy;   // Source
    2128                 :      52444 :     nEndRow -= nDy;
    2129                 :            : 
    2130                 :      52444 :     SCROW nDestStart = Max((long)((long)nStartRow + nDy), (long) 0);
    2131                 :      52444 :     SCROW nDestEnd = Min((long)((long)nEndRow + nDy), (long) MAXROW);
    2132                 :            : 
    2133                 :      52444 :     ScDocumentPool* pSourceDocPool = pDocument->GetPool();
    2134                 :      52444 :     ScDocumentPool* pDestDocPool = rAttrArray.pDocument->GetPool();
    2135                 :      52444 :     bool bSamePool = (pSourceDocPool==pDestDocPool);
    2136                 :            : 
    2137 [ +  + ][ +  + ]:     108740 :     for (SCSIZE i = 0; (i < nCount) && (nDestStart <= nDestEnd); i++)
                 [ +  + ]
    2138                 :            :     {
    2139         [ +  + ]:      56296 :         if (pData[i].nRow >= nStartRow)
    2140                 :            :         {
    2141                 :      55590 :             const ScPatternAttr* pOldPattern = pData[i].pPattern;
    2142                 :            :             const ScPatternAttr* pNewPattern;
    2143                 :            : 
    2144         [ +  + ]:      55590 :             if (IsDefaultItem( pOldPattern ))
    2145                 :            :             {
    2146                 :            :                 // default: nothing changed
    2147                 :            : 
    2148                 :            :                 pNewPattern = (const ScPatternAttr*)
    2149                 :      49946 :                                 &pDestDocPool->GetDefaultItem( ATTR_PATTERN );
    2150                 :            :             }
    2151         [ -  + ]:       5644 :             else if ( nStripFlags )
    2152                 :            :             {
    2153         [ #  # ]:          0 :                 ScPatternAttr* pTmpPattern = new ScPatternAttr( *pOldPattern );
    2154                 :          0 :                 sal_Int16 nNewFlags = 0;
    2155         [ #  # ]:          0 :                 if ( nStripFlags != SC_MF_ALL )
    2156                 :          0 :                     nNewFlags = ((const ScMergeFlagAttr&)pTmpPattern->GetItem(ATTR_MERGE_FLAG)).
    2157                 :          0 :                                 GetValue() & ~nStripFlags;
    2158                 :            : 
    2159         [ #  # ]:          0 :                 if ( nNewFlags )
    2160         [ #  # ]:          0 :                     pTmpPattern->GetItemSet().Put( ScMergeFlagAttr( nNewFlags ) );
    2161                 :            :                 else
    2162                 :          0 :                     pTmpPattern->GetItemSet().ClearItem( ATTR_MERGE_FLAG );
    2163                 :            : 
    2164         [ #  # ]:          0 :                 if (bSamePool)
    2165                 :          0 :                     pNewPattern = (ScPatternAttr*) &pDestDocPool->Put(*pTmpPattern);
    2166                 :            :                 else
    2167                 :          0 :                     pNewPattern = pTmpPattern->PutInPool( rAttrArray.pDocument, pDocument );
    2168         [ #  # ]:          0 :                 delete pTmpPattern;
    2169                 :            :             }
    2170                 :            :             else
    2171                 :            :             {
    2172         [ +  + ]:       5644 :                 if (bSamePool)
    2173                 :       5630 :                     pNewPattern = (ScPatternAttr*) &pDestDocPool->Put(*pOldPattern);
    2174                 :            :                 else
    2175                 :         14 :                     pNewPattern = pOldPattern->PutInPool( rAttrArray.pDocument, pDocument );
    2176                 :            :             }
    2177                 :            : 
    2178                 :            :             rAttrArray.SetPatternArea(nDestStart,
    2179                 :      55590 :                             Min((SCROW)(pData[i].nRow + nDy), nDestEnd), pNewPattern);
    2180                 :            :         }
    2181                 :            : 
    2182                 :            :         // when pasting from clipboard and skipping filtered rows, the adjusted
    2183                 :            :         // end position can be negative
    2184                 :      56296 :         nDestStart = Max((long)nDestStart, (long)(pData[i].nRow + nDy + 1));
    2185                 :            :     }
    2186                 :      52444 : }
    2187                 :            : 
    2188                 :            : 
    2189                 :            : // leave flags
    2190                 :            : // summarized with CopyArea
    2191                 :            : 
    2192                 :         95 : void ScAttrArray::CopyAreaSafe( SCROW nStartRow, SCROW nEndRow, long nDy, ScAttrArray& rAttrArray )
    2193                 :            : {
    2194                 :         95 :     nStartRow -= nDy;  // Source
    2195                 :         95 :     nEndRow -= nDy;
    2196                 :            : 
    2197                 :         95 :     SCROW nDestStart = Max((long)((long)nStartRow + nDy), (long) 0);
    2198                 :         95 :     SCROW nDestEnd = Min((long)((long)nEndRow + nDy), (long) MAXROW);
    2199                 :            : 
    2200         [ +  - ]:         95 :     if ( !rAttrArray.HasAttrib( nDestStart, nDestEnd, HASATTR_OVERLAPPED ) )
    2201                 :            :     {
    2202                 :         95 :         CopyArea( nStartRow+nDy, nEndRow+nDy, nDy, rAttrArray );
    2203                 :         95 :         return;
    2204                 :            :     }
    2205                 :            : 
    2206                 :          0 :     ScDocumentPool* pSourceDocPool = pDocument->GetPool();
    2207                 :          0 :     ScDocumentPool* pDestDocPool = rAttrArray.pDocument->GetPool();
    2208                 :          0 :     bool bSamePool = (pSourceDocPool==pDestDocPool);
    2209                 :            : 
    2210 [ #  # ][ #  # ]:          0 :     for (SCSIZE i = 0; (i < nCount) && (nDestStart <= nDestEnd); i++)
                 [ #  # ]
    2211                 :            :     {
    2212         [ #  # ]:          0 :         if (pData[i].nRow >= nStartRow)
    2213                 :            :         {
    2214                 :          0 :             const ScPatternAttr* pOldPattern = pData[i].pPattern;
    2215                 :            :             const ScPatternAttr* pNewPattern;
    2216                 :            : 
    2217         [ #  # ]:          0 :             if (bSamePool)
    2218                 :          0 :                 pNewPattern = (ScPatternAttr*) &pDestDocPool->Put(*pOldPattern);
    2219                 :            :             else
    2220                 :          0 :                 pNewPattern = pOldPattern->PutInPool( rAttrArray.pDocument, pDocument );
    2221                 :            : 
    2222                 :            :             rAttrArray.SetPatternAreaSafe(nDestStart,
    2223                 :          0 :                             Min((SCROW)(pData[i].nRow + nDy), nDestEnd), pNewPattern, false);
    2224                 :            :         }
    2225                 :            : 
    2226                 :            :         // when pasting from clipboard and skipping filtered rows, the adjusted
    2227                 :            :         // end position can be negative
    2228                 :          0 :         nDestStart = Max((long)nDestStart, (long)(pData[i].nRow + nDy + 1));
    2229                 :            :     }
    2230                 :            : }
    2231                 :            : 
    2232                 :            : 
    2233                 :          0 : SCsROW ScAttrArray::SearchStyle( SCsROW nRow, const ScStyleSheet* pSearchStyle,
    2234                 :            :                                     bool bUp, ScMarkArray* pMarkArray )
    2235                 :            : {
    2236                 :          0 :     bool bFound = false;
    2237                 :            : 
    2238         [ #  # ]:          0 :     if (pMarkArray)
    2239                 :            :     {
    2240         [ #  # ]:          0 :         nRow = pMarkArray->GetNextMarked( nRow, bUp );
    2241         [ #  # ]:          0 :         if (!VALIDROW(nRow))
    2242                 :          0 :             return nRow;
    2243                 :            :     }
    2244                 :            : 
    2245                 :            :     SCSIZE nIndex;
    2246                 :          0 :     Search(nRow, nIndex);
    2247                 :          0 :     const ScPatternAttr* pPattern = pData[nIndex].pPattern;
    2248                 :            : 
    2249 [ #  # ][ #  # ]:          0 :     while (nIndex < nCount && !bFound)
                 [ #  # ]
    2250                 :            :     {
    2251         [ #  # ]:          0 :         if (pPattern->GetStyleSheet() == pSearchStyle)
    2252                 :            :         {
    2253         [ #  # ]:          0 :             if (pMarkArray)
    2254                 :            :             {
    2255         [ #  # ]:          0 :                 nRow = pMarkArray->GetNextMarked( nRow, bUp );
    2256         [ #  # ]:          0 :                 SCROW nStart = nIndex ? pData[nIndex-1].nRow+1 : 0;
    2257 [ #  # ][ #  # ]:          0 :                 if (nRow >= nStart && nRow <= pData[nIndex].nRow)
    2258                 :          0 :                     bFound = true;
    2259                 :            :             }
    2260                 :            :             else
    2261                 :          0 :                 bFound = true;
    2262                 :            :         }
    2263                 :            : 
    2264         [ #  # ]:          0 :         if (!bFound)
    2265                 :            :         {
    2266         [ #  # ]:          0 :             if (bUp)
    2267                 :            :             {
    2268         [ #  # ]:          0 :                 if (nIndex==0)
    2269                 :            :                 {
    2270                 :          0 :                     nIndex = nCount;
    2271                 :          0 :                     nRow = -1;
    2272                 :            :                 }
    2273                 :            :                 else
    2274                 :            :                 {
    2275                 :          0 :                     --nIndex;
    2276                 :          0 :                     nRow = pData[nIndex].nRow;
    2277                 :          0 :                     pPattern = pData[nIndex].pPattern;
    2278                 :            :                 }
    2279                 :            :             }
    2280                 :            :             else
    2281                 :            :             {
    2282                 :          0 :                 nRow = pData[nIndex].nRow+1;
    2283                 :          0 :                 ++nIndex;
    2284         [ #  # ]:          0 :                 if (nIndex<nCount)
    2285                 :          0 :                     pPattern = pData[nIndex].pPattern;
    2286                 :            :             }
    2287                 :            :         }
    2288                 :            :     }
    2289                 :            : 
    2290                 :            :     OSL_ENSURE( bFound || !ValidRow(nRow), "Internal failure in in ScAttrArray::SearchStyle" );
    2291                 :            : 
    2292                 :          0 :     return nRow;
    2293                 :            : }
    2294                 :            : 
    2295                 :            : 
    2296                 :          0 : bool ScAttrArray::SearchStyleRange( SCsROW& rRow, SCsROW& rEndRow,
    2297                 :            :                         const ScStyleSheet* pSearchStyle, bool bUp, ScMarkArray* pMarkArray )
    2298                 :            : {
    2299                 :          0 :     SCsROW nStartRow = SearchStyle( rRow, pSearchStyle, bUp, pMarkArray );
    2300         [ #  # ]:          0 :     if (VALIDROW(nStartRow))
    2301                 :            :     {
    2302                 :            :         SCSIZE nIndex;
    2303                 :          0 :         Search(nStartRow,nIndex);
    2304                 :            : 
    2305                 :          0 :         rRow = nStartRow;
    2306         [ #  # ]:          0 :         if (bUp)
    2307                 :            :         {
    2308         [ #  # ]:          0 :             if (nIndex>0)
    2309                 :          0 :                 rEndRow = pData[nIndex-1].nRow + 1;
    2310                 :            :             else
    2311                 :          0 :                 rEndRow = 0;
    2312         [ #  # ]:          0 :             if (pMarkArray)
    2313                 :            :             {
    2314         [ #  # ]:          0 :                 SCROW nMarkEnd = pMarkArray->GetMarkEnd( nStartRow, true );
    2315         [ #  # ]:          0 :                 if (nMarkEnd>rEndRow)
    2316                 :          0 :                     rEndRow = nMarkEnd;
    2317                 :            :             }
    2318                 :            :         }
    2319                 :            :         else
    2320                 :            :         {
    2321                 :          0 :             rEndRow = pData[nIndex].nRow;
    2322         [ #  # ]:          0 :             if (pMarkArray)
    2323                 :            :             {
    2324         [ #  # ]:          0 :                 SCROW nMarkEnd = pMarkArray->GetMarkEnd( nStartRow, false );
    2325         [ #  # ]:          0 :                 if (nMarkEnd<rEndRow)
    2326                 :          0 :                     rEndRow = nMarkEnd;
    2327                 :            :             }
    2328                 :            :         }
    2329                 :            : 
    2330                 :          0 :         return true;
    2331                 :            :     }
    2332                 :            :     else
    2333                 :          0 :         return false;
    2334                 :            : }
    2335                 :            : 
    2336                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10