LCOV - code coverage report
Current view: top level - sc/source/core/data - markarr.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 179 190 94.2 %
Date: 2014-04-11 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "markarr.hxx"
      21             : #include "global.hxx"
      22             : #include "address.hxx"
      23             : 
      24             : // STATIC DATA -----------------------------------------------------------
      25             : 
      26      842752 : ScMarkArray::ScMarkArray() :
      27             :     nCount( 0 ),
      28             :     nLimit( 0 ),
      29      842752 :     pData( NULL )
      30             : {
      31             :     // special case "no marks" with pData = NULL
      32      842752 : }
      33             : 
      34      840704 : ScMarkArray::~ScMarkArray()
      35             : {
      36      840704 :     delete[] pData;
      37      840704 : }
      38             : 
      39       36163 : void ScMarkArray::Reset( bool bMarked )
      40             : {
      41             :     // always create pData here
      42             :     // (or have separate method to ensure pData)
      43             : 
      44       36163 :     delete[] pData;
      45             : 
      46       36163 :     nCount = nLimit = 1;
      47       36163 :     pData = new ScMarkEntry[1];
      48       36163 :     pData[0].nRow = MAXROW;
      49       36163 :     pData[0].bMarked = bMarked;
      50       36163 : }
      51             : 
      52      150598 : bool ScMarkArray::Search( SCROW nRow, SCSIZE& nIndex ) const
      53             : {
      54      150598 :     long    nHi         = static_cast<long>(nCount) - 1;
      55      150598 :     long    i           = 0;
      56      150598 :     bool    bFound      = (nCount == 1);
      57      150598 :     if (pData)
      58             :     {
      59      150158 :         long    nLo         = 0;
      60      150158 :         long    nStartRow   = 0;
      61      563842 :         while ( !bFound && nLo <= nHi )
      62             :         {
      63      263526 :             i = (nLo + nHi) / 2;
      64      263526 :             if (i > 0)
      65      137271 :                 nStartRow = (long) pData[i - 1].nRow;
      66             :             else
      67      126255 :                 nStartRow = -1;
      68      263526 :             long nEndRow = (long) pData[i].nRow;
      69      263526 :             if (nEndRow < (long) nRow)
      70      131321 :                 nLo = ++i;
      71             :             else
      72      132205 :                 if (nStartRow >= (long) nRow)
      73         462 :                     nHi = --i;
      74             :                 else
      75      131743 :                     bFound = true;
      76             :         }
      77             :     }
      78             :     else
      79         440 :         bFound = false;
      80             : 
      81      150598 :     if (bFound)
      82      150158 :         nIndex=(SCSIZE)i;
      83             :     else
      84         440 :         nIndex=0;
      85      150598 :     return bFound;
      86             : }
      87             : 
      88        2604 : bool ScMarkArray::GetMark( SCROW nRow ) const
      89             : {
      90             :     SCSIZE i;
      91        2604 :     if (Search( nRow, i ))
      92        2411 :         return pData[i].bMarked;
      93             :     else
      94         193 :         return false;
      95             : 
      96             : }
      97             : 
      98      165820 : void ScMarkArray::SetMarkArea( SCROW nStartRow, SCROW nEndRow, bool bMarked )
      99             : {
     100      165820 :     if (ValidRow(nStartRow) && ValidRow(nEndRow))
     101             :     {
     102      165820 :         if ((nStartRow == 0) && (nEndRow == MAXROW))
     103             :         {
     104       13550 :             Reset(bMarked);
     105             :         }
     106             :         else
     107             :         {
     108      152270 :             if (!pData)
     109       20565 :                 Reset(false);   // create pData for further processing - could use special case handling!
     110             : 
     111      152270 :             SCSIZE nNeeded = nCount + 2;
     112      152270 :             if ( nLimit < nNeeded )
     113             :             {
     114       21444 :                 nLimit += SC_MARKARRAY_DELTA;
     115       21444 :                 if ( nLimit < nNeeded )
     116           0 :                     nLimit = nNeeded;
     117       21444 :                 ScMarkEntry* pNewData = new ScMarkEntry[nLimit];
     118       21444 :                 memcpy( pNewData, pData, nCount*sizeof(ScMarkEntry) );
     119       21444 :                 delete[] pData;
     120       21444 :                 pData = pNewData;
     121             :             }
     122             : 
     123             :             SCSIZE ni;          // number of entries in beginning
     124             :             SCSIZE nInsert;     // insert position (MAXROW+1 := no insert)
     125      152270 :             sal_Bool bCombined = false;
     126      152270 :             sal_Bool bSplit = false;
     127      152270 :             if ( nStartRow > 0 )
     128             :             {
     129             :                 // skip beginning
     130             :                 SCSIZE nIndex;
     131      145475 :                 Search( nStartRow, nIndex );
     132      145475 :                 ni = nIndex;
     133             : 
     134      145475 :                 nInsert = MAXROWCOUNT;
     135      145475 :                 if ( pData[ni].bMarked != bMarked )
     136             :                 {
     137      130795 :                     if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
     138             :                     {   // may be a split or a simple insert or just a shrink,
     139             :                         // row adjustment is done further down
     140        3065 :                         if ( pData[ni].nRow > nEndRow )
     141        2985 :                             bSplit = sal_True;
     142        3065 :                         ni++;
     143        3065 :                         nInsert = ni;
     144             :                     }
     145      127730 :                     else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
     146      127730 :                         nInsert = ni;
     147             :                 }
     148      145475 :                 if ( ni > 0 && pData[ni-1].bMarked == bMarked )
     149             :                 {   // combine
     150      127730 :                     pData[ni-1].nRow = nEndRow;
     151      127730 :                     nInsert = MAXROWCOUNT;
     152      127730 :                     bCombined = sal_True;
     153             :                 }
     154             :             }
     155             :             else
     156             :         {
     157        6795 :                 nInsert = 0;
     158        6795 :                 ni = 0;
     159             :         }
     160             : 
     161      152270 :             SCSIZE nj = ni;     // stop position of range to replace
     162      310414 :             while ( nj < nCount && pData[nj].nRow <= nEndRow )
     163        5874 :                 nj++;
     164      152270 :             if ( !bSplit )
     165             :             {
     166      149285 :                 if ( nj < nCount && pData[nj].bMarked == bMarked )
     167             :                 {   // combine
     168       15393 :                     if ( ni > 0 )
     169             :                     {
     170          82 :                         if ( pData[ni-1].bMarked == bMarked )
     171             :                         {   // adjacent entries
     172          40 :                             pData[ni-1].nRow = pData[nj].nRow;
     173          40 :                             nj++;
     174             :                         }
     175          42 :                         else if ( ni == nInsert )
     176           8 :                             pData[ni-1].nRow = nStartRow - 1;   // shrink
     177             :                     }
     178       15393 :                     nInsert = MAXROWCOUNT;
     179       15393 :                     bCombined = sal_True;
     180             :                 }
     181      133892 :                 else if ( ni > 0 && ni == nInsert )
     182          72 :                     pData[ni-1].nRow = nStartRow - 1;   // shrink
     183             :             }
     184      152270 :             if ( ni < nj )
     185             :             {   // remove middle entries
     186        5874 :                 if ( !bCombined )
     187             :                 {   // replace one entry
     188         618 :                     pData[ni].nRow = nEndRow;
     189         618 :                     pData[ni].bMarked = bMarked;
     190         618 :                     ni++;
     191         618 :                     nInsert = MAXROWCOUNT;
     192             :                 }
     193        5874 :                 if ( ni < nj )
     194             :                 {   // remove entries
     195        5256 :                     memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScMarkEntry) );
     196        5256 :                     nCount -= nj - ni;
     197             :                 }
     198             :             }
     199             : 
     200      152270 :             if ( nInsert < sal::static_int_cast<SCSIZE>(MAXROWCOUNT) )
     201             :             {   // insert or append new entry
     202        8569 :                 if ( nInsert <= nCount )
     203             :                 {
     204        8569 :                     if ( !bSplit )
     205        5584 :                         memmove( pData + nInsert + 1, pData + nInsert,
     206       11168 :                             (nCount - nInsert) * sizeof(ScMarkEntry) );
     207             :                     else
     208             :                     {
     209        2985 :                         memmove( pData + nInsert + 2, pData + nInsert,
     210        5970 :                             (nCount - nInsert) * sizeof(ScMarkEntry) );
     211        2985 :                         pData[nInsert+1] = pData[nInsert-1];
     212        2985 :                         nCount++;
     213             :                     }
     214             :                 }
     215        8569 :                 if ( nInsert )
     216        3057 :                     pData[nInsert-1].nRow = nStartRow - 1;
     217        8569 :                 pData[nInsert].nRow = nEndRow;
     218        8569 :                 pData[nInsert].bMarked = bMarked;
     219        8569 :                 nCount++;
     220             :             }
     221             :         }
     222             :     }
     223      165820 : }
     224             : 
     225          36 : bool ScMarkArray::IsAllMarked( SCROW nStartRow, SCROW nEndRow ) const
     226             : {
     227             :     SCSIZE nStartIndex;
     228             :     SCSIZE nEndIndex;
     229             : 
     230          36 :     if (Search( nStartRow, nStartIndex ))
     231          36 :         if (pData[nStartIndex].bMarked)
     232          36 :             if (Search( nEndRow, nEndIndex ))
     233          36 :                 if (nEndIndex==nStartIndex)
     234          36 :                     return true;
     235             : 
     236           0 :     return false;
     237             : }
     238             : 
     239         130 : bool ScMarkArray::HasOneMark( SCROW& rStartRow, SCROW& rEndRow ) const
     240             : {
     241         130 :     bool bRet = false;
     242         130 :     if ( nCount == 1 )
     243             :     {
     244          26 :         if ( pData[0].bMarked )
     245             :         {
     246          26 :             rStartRow = 0;
     247          26 :             rEndRow = MAXROW;
     248          26 :             bRet = true;
     249             :         }
     250             :     }
     251         104 :     else if ( nCount == 2 )
     252             :     {
     253          13 :         if ( pData[0].bMarked )
     254             :         {
     255          13 :             rStartRow = 0;
     256          13 :             rEndRow = pData[0].nRow;
     257             :         }
     258             :         else
     259             :         {
     260           0 :             rStartRow = pData[0].nRow + 1;
     261           0 :             rEndRow = MAXROW;
     262             :         }
     263          13 :         bRet = true;
     264             :     }
     265          91 :     else if ( nCount == 3 )
     266             :     {
     267          78 :         if ( pData[1].bMarked )
     268             :         {
     269          78 :             rStartRow = pData[0].nRow + 1;
     270          78 :             rEndRow = pData[1].nRow;
     271          78 :             bRet = true;
     272             :         }
     273             :     }
     274         130 :     return bRet;
     275             : }
     276             : 
     277      233472 : void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const
     278             : {
     279      233472 :     delete[] rDestMarkArray.pData;
     280             : 
     281      233472 :     if (pData)
     282             :     {
     283        1137 :         rDestMarkArray.pData = new ScMarkEntry[nCount];
     284        1137 :         memcpy( rDestMarkArray.pData, pData, nCount * sizeof(ScMarkEntry) );
     285             :     }
     286             :     else
     287      232335 :         rDestMarkArray.pData = NULL;
     288             : 
     289      233472 :     rDestMarkArray.nCount = rDestMarkArray.nLimit = nCount;
     290      233472 : }
     291             : 
     292        2056 : SCsROW ScMarkArray::GetNextMarked( SCsROW nRow, bool bUp ) const
     293             : {
     294        2056 :     if (!pData)
     295        2048 :         const_cast<ScMarkArray*>(this)->Reset(false);   // create pData for further processing
     296             : 
     297        2056 :     SCsROW nRet = nRow;
     298        2056 :     if (ValidRow(nRow))
     299             :     {
     300             :         SCSIZE nIndex;
     301        2056 :         Search(nRow, nIndex);
     302        2056 :         if (!pData[nIndex].bMarked)
     303             :         {
     304        2050 :             if (bUp)
     305             :             {
     306           0 :                 if (nIndex>0)
     307           0 :                     nRet = pData[nIndex-1].nRow;
     308             :                 else
     309           0 :                     nRet = -1;
     310             :             }
     311             :             else
     312        2050 :                 nRet = pData[nIndex].nRow + 1;
     313             :         }
     314             :     }
     315        2056 :     return nRet;
     316             : }
     317             : 
     318           6 : SCROW ScMarkArray::GetMarkEnd( SCROW nRow, bool bUp ) const
     319             : {
     320           6 :     if (!pData)
     321           0 :         const_cast<ScMarkArray*>(this)->Reset(false);   // create pData for further processing
     322             : 
     323             :     SCROW nRet;
     324             :     SCSIZE nIndex;
     325           6 :     Search(nRow, nIndex);
     326             :     OSL_ENSURE( pData[nIndex].bMarked, "GetMarkEnd without bMarked" );
     327           6 :     if (bUp)
     328             :     {
     329           0 :         if (nIndex>0)
     330           0 :             nRet = pData[nIndex-1].nRow + 1;
     331             :         else
     332           0 :             nRet = 0;
     333             :     }
     334             :     else
     335           6 :         nRet = pData[nIndex].nRow;
     336             : 
     337           6 :     return nRet;
     338             : }
     339             : 
     340             : 
     341             : //  -------------- Iterator ----------------------------------------------
     342             : 
     343             : 
     344      975495 : ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
     345             :     pArray( pNewArray ),
     346      975495 :     nPos( 0 )
     347             : {
     348      975495 : }
     349             : 
     350      975495 : ScMarkArrayIter::~ScMarkArrayIter()
     351             : {
     352      975495 : }
     353             : 
     354     1530840 : bool ScMarkArrayIter::Next( SCROW& rTop, SCROW& rBottom )
     355             : {
     356     1530840 :     if ( nPos >= pArray->nCount )
     357      464487 :         return false;
     358     2527917 :     while (!pArray->pData[nPos].bMarked)
     359             :     {
     360      906219 :         ++nPos;
     361      906219 :         if ( nPos >= pArray->nCount )
     362      511008 :             return false;
     363             :     }
     364      555345 :     rBottom = pArray->pData[nPos].nRow;
     365      555345 :     if (nPos==0)
     366      160134 :         rTop = 0;
     367             :     else
     368      395211 :         rTop = pArray->pData[nPos-1].nRow + 1;
     369      555345 :     ++nPos;
     370      555345 :     return true;
     371             : }
     372             : 
     373             : 
     374             : 
     375             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10