LCOV - code coverage report
Current view: top level - sc/source/core/inc - bcaslot.hxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 43 43 100.0 %
Date: 2015-06-13 12:38:46 Functions: 33 33 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             : #ifndef INCLUDED_SC_SOURCE_CORE_INC_BCASLOT_HXX
      21             : #define INCLUDED_SC_SOURCE_CORE_INC_BCASLOT_HXX
      22             : 
      23             : #include <functional>
      24             : #include <set>
      25             : #include <unordered_set>
      26             : #include <boost/ptr_container/ptr_map.hpp>
      27             : 
      28             : #include <svl/broadcast.hxx>
      29             : 
      30             : #include "global.hxx"
      31             : #include "brdcst.hxx"
      32             : #include <columnspanset.hxx>
      33             : 
      34             : class ScBroadcastArea;
      35             : 
      36             : namespace sc {
      37             : 
      38          45 : struct AreaListener
      39             : {
      40             :     ScRange maArea;
      41             :     bool mbGroupListening;
      42             :     SvtListener* mpListener;
      43             : 
      44             :     struct SortByArea : std::binary_function<AreaListener, AreaListener, bool>
      45             :     {
      46             :         bool operator() ( const AreaListener& rLeft, const AreaListener& rRight ) const;
      47             :     };
      48             : };
      49             : 
      50             : }
      51             : 
      52             : /**
      53             :     Used in a Unique Associative Container.
      54             :  */
      55             : 
      56        3708 : class ScBroadcastArea : boost::noncopyable
      57             : {
      58             : private:
      59             :     ScBroadcastArea*    pUpdateChainNext;
      60             :     SvtBroadcaster      aBroadcaster;
      61             :     ScRange             aRange;
      62             :     sal_uLong               nRefCount;
      63             : 
      64             :     bool mbInUpdateChain:1;
      65             :     bool mbGroupListening:1;
      66             : 
      67             : public:
      68             :     ScBroadcastArea( const ScRange& rRange );
      69             : 
      70        8400 :     inline SvtBroadcaster&       GetBroadcaster()       { return aBroadcaster; }
      71             :     inline const SvtBroadcaster& GetBroadcaster() const { return aBroadcaster; }
      72        7503 :     inline void         UpdateRange( const ScRange& rNewRange )
      73        7503 :                             { aRange = rNewRange; }
      74       16400 :     inline const ScRange&   GetRange() const { return aRange; }
      75             :     inline const ScAddress& GetStart() const { return aRange.aStart; }
      76             :     inline const ScAddress& GetEnd() const { return aRange.aEnd; }
      77        3532 :     inline void         IncRef() { ++nRefCount; }
      78        3456 :     inline sal_uLong        DecRef() { return nRefCount ? --nRefCount : 0; }
      79         435 :     inline sal_uLong        GetRef() { return nRefCount; }
      80          98 :     inline ScBroadcastArea* GetUpdateChainNext() const { return pUpdateChainNext; }
      81          49 :     inline void         SetUpdateChainNext( ScBroadcastArea* p ) { pUpdateChainNext = p; }
      82          63 :     inline bool         IsInUpdateChain() const { return mbInUpdateChain; }
      83          98 :     inline void         SetInUpdateChain( bool b ) { mbInUpdateChain = b; }
      84             : 
      85       11601 :     inline bool IsGroupListening() const { return mbGroupListening; }
      86        9693 :     void SetGroupListening( bool b ) { mbGroupListening = b; }
      87             : 
      88             :     /** Equalness of this or range. */
      89             :     inline  bool        operator==( const ScBroadcastArea & rArea ) const;
      90             : };
      91             : 
      92        5173 : inline bool ScBroadcastArea::operator==( const ScBroadcastArea & rArea ) const
      93             : {
      94        5173 :     return aRange == rArea.aRange && mbGroupListening == rArea.mbGroupListening;
      95             : }
      96             : 
      97             : struct ScBroadcastAreaEntry
      98             : {
      99             :     ScBroadcastArea* mpArea;
     100             :     mutable bool     mbErasure;     ///< TRUE if marked for erasure in this set
     101             : 
     102       10987 :     ScBroadcastAreaEntry( ScBroadcastArea* p ) : mpArea( p), mbErasure( false) {}
     103             : };
     104             : 
     105             : struct ScBroadcastAreaHash
     106             : {
     107       10987 :     size_t operator()( const ScBroadcastAreaEntry& rEntry ) const
     108             :     {
     109       10987 :         return rEntry.mpArea->GetRange().hashArea() + static_cast<size_t>(rEntry.mpArea->IsGroupListening());
     110             :     }
     111             : };
     112             : 
     113             : struct ScBroadcastAreaEqual
     114             : {
     115        5173 :     bool operator()( const ScBroadcastAreaEntry& rEntry1, const ScBroadcastAreaEntry& rEntry2) const
     116             :     {
     117        5173 :         return *rEntry1.mpArea == *rEntry2.mpArea;
     118             :     }
     119             : };
     120             : 
     121             : typedef std::unordered_set< ScBroadcastAreaEntry, ScBroadcastAreaHash, ScBroadcastAreaEqual > ScBroadcastAreas;
     122             : 
     123             : struct ScBroadcastAreaBulkHash
     124             : {
     125         402 :     size_t operator()( const ScBroadcastArea* p ) const
     126             :     {
     127         402 :         return reinterpret_cast<size_t>(p);
     128             :     }
     129             : };
     130             : 
     131             : struct ScBroadcastAreaBulkEqual
     132             : {
     133         192 :     bool operator()( const ScBroadcastArea* p1, const ScBroadcastArea* p2) const
     134             :     {
     135         192 :         return p1 == p2;
     136             :     }
     137             : };
     138             : 
     139             : typedef std::unordered_set< const ScBroadcastArea*, ScBroadcastAreaBulkHash,
     140             :         ScBroadcastAreaBulkEqual > ScBroadcastAreasBulk;
     141             : 
     142             : class ScBroadcastAreaSlotMachine;
     143             : 
     144             : /// Collection of BroadcastAreas
     145             : class ScBroadcastAreaSlot
     146             : {
     147             : private:
     148             :     ScBroadcastAreas    aBroadcastAreaTbl;
     149             :     mutable ScBroadcastArea aTmpSeekBroadcastArea;      // for FindBroadcastArea()
     150             :     ScDocument*         pDoc;
     151             :     ScBroadcastAreaSlotMachine* pBASM;
     152             :     bool                mbInBroadcastIteration;
     153             : 
     154             :     /**
     155             :      * If true, the slot has at least one area broadcaster marked for removal.
     156             :      * This flag is used only during broadcast iteration, to speed up
     157             :      * iteration.  Using this flag is cheaper than dereferencing each iterator
     158             :      * and checking its own flag inside especially when no areas are marked
     159             :      * for removal.
     160             :      */
     161             :     bool mbHasErasedArea;
     162             : 
     163             :     ScBroadcastAreas::iterator FindBroadcastArea( const ScRange& rRange, bool bGroupListening );
     164             : 
     165             :     /**
     166             :         More hypothetical (memory would probably be doomed anyway) check
     167             :         whether there would be an overflow when adding an area, setting the
     168             :         proper state if so.
     169             : 
     170             :         @return true if a HardRecalcState is effective and area is not to be
     171             :         added.
     172             :       */
     173             :     bool                CheckHardRecalcStateCondition() const;
     174             : 
     175             :     /** Finally erase all areas pushed as to-be-erased. */
     176             :     void                FinallyEraseAreas();
     177             : 
     178         591 :     static bool         isMarkedErased( const ScBroadcastAreas::const_iterator& rIter )
     179             :     {
     180         591 :         return rIter->mbErasure;
     181             :     }
     182             : 
     183             : public:
     184             :                         ScBroadcastAreaSlot( ScDocument* pDoc,
     185             :                                         ScBroadcastAreaSlotMachine* pBASM );
     186             :                         ~ScBroadcastAreaSlot();
     187             :     const ScBroadcastAreas& GetBroadcastAreas() const
     188             :                                             { return aBroadcastAreaTbl; }
     189             : 
     190             :     /**
     191             :         Only here new ScBroadcastArea objects are created, prevention of dupes.
     192             : 
     193             :         @param rpArea
     194             :             If NULL, a new ScBroadcastArea is created and assigned ton the
     195             :             reference if a matching area wasn't found. If a matching area was
     196             :             found, that is assigned. In any case, the SvtListener is added to
     197             :             the broadcaster.
     198             : 
     199             :             If not NULL then no listeners are startet, only the area is
     200             :             inserted and the reference count incremented. Effectively the same
     201             :             as InsertListeningArea(), so use that instead.
     202             : 
     203             :         @return
     204             :             true if rpArea passed was NULL and ScBroadcastArea is newly
     205             :             created.
     206             :      */
     207             :     bool StartListeningArea(
     208             :         const ScRange& rRange, bool bGroupListening, SvtListener* pListener, ScBroadcastArea*& rpArea );
     209             : 
     210             :     /**
     211             :         Insert a ScBroadcastArea obtained via StartListeningArea() to
     212             :         subsequent slots.
     213             :      */
     214             :     void                InsertListeningArea( ScBroadcastArea* pArea );
     215             : 
     216             :     void EndListeningArea(
     217             :         const ScRange& rRange, bool bGroupListening, SvtListener* pListener, ScBroadcastArea*& rpArea );
     218             : 
     219             :     bool AreaBroadcast( const ScRange& rRange, sal_uLong nHint );
     220             :     bool                AreaBroadcast( const ScHint& rHint );
     221             :     void                DelBroadcastAreasInRange( const ScRange& rRange );
     222             :     void                UpdateRemove( UpdateRefMode eUpdateRefMode,
     223             :                                         const ScRange& rRange,
     224             :                                         SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
     225             :     void                UpdateRemoveArea( ScBroadcastArea* pArea );
     226             :     void                UpdateInsert( ScBroadcastArea* pArea );
     227             : 
     228        1946 :     bool                IsInBroadcastIteration() const { return mbInBroadcastIteration; }
     229             : 
     230             :     /** Erase an area from set and delete it if last reference, or if
     231             :         mbInBroadcastIteration is set push it to the vector of to-be-erased
     232             :         areas instead.
     233             : 
     234             :         Meant to be used internally and from ScBroadcastAreaSlotMachine only.
     235             :      */
     236             :     void                EraseArea( ScBroadcastAreas::iterator& rIter );
     237             : 
     238             :     void GetAllListeners(
     239             :         const ScRange& rRange, std::vector<sc::AreaListener>& rListeners,
     240             :         sc::AreaOverlapType eType, sc::ListenerGroupType eGroup );
     241             : 
     242             : #if DEBUG_AREA_BROADCASTER
     243             :     void Dump() const;
     244             : #endif
     245             : };
     246             : 
     247             : /**
     248             :     BroadcastAreaSlots and their management, once per document.
     249             :  */
     250             : 
     251             : class  ScBroadcastAreaSlotMachine
     252             : {
     253             : private:
     254             :     typedef boost::ptr_map<ScBroadcastArea*, sc::ColumnSpanSet> BulkGroupAreasType;
     255             : 
     256             :     /**
     257             :         Slot offset arrangement of columns and rows, once per sheet.
     258             : 
     259             :         +---+---+
     260             :         | 0 | 3 |
     261             :         +---+---+
     262             :         | 1 | 4 |
     263             :         +---+---+
     264             :         | 2 | 5 |
     265             :         +---+---+
     266             :      */
     267             : 
     268             :     class TableSlots
     269             :     {
     270             :     public:
     271             :                                         TableSlots();
     272             :                                         ~TableSlots();
     273        7705 :         inline ScBroadcastAreaSlot**    getSlots() { return ppSlots; }
     274             : 
     275             :         /**
     276             :             Obtain slot pointer, no check on validity! It is assumed that
     277             :             all calls are made with the results of ComputeSlotOffset(),
     278             :             ComputeAreaPoints() and ComputeNextSlot()
     279             :           */
     280        5377 :         inline ScBroadcastAreaSlot*     getAreaSlot( SCSIZE nOff ) { return *(ppSlots + nOff); }
     281             : 
     282             :     private:
     283             :         ScBroadcastAreaSlot**   ppSlots;
     284             : 
     285             :         TableSlots( const TableSlots& ) SAL_DELETED_FUNCTION;
     286             :         TableSlots& operator=( const TableSlots& ) SAL_DELETED_FUNCTION;
     287             :     };
     288             : 
     289             :     typedef ::std::map< SCTAB, TableSlots* > TableSlotsMap;
     290             : 
     291             :     typedef ::std::vector< ::std::pair< ScBroadcastAreaSlot*, ScBroadcastAreas::iterator > > AreasToBeErased;
     292             : 
     293             : private:
     294             :     ScBroadcastAreasBulk  aBulkBroadcastAreas;
     295             :     BulkGroupAreasType maBulkGroupAreas;
     296             :     TableSlotsMap         aTableSlotsMap;
     297             :     AreasToBeErased       maAreasToBeErased;
     298             :     SvtBroadcaster       *pBCAlways;             // for the RC_ALWAYS special range
     299             :     ScDocument           *pDoc;
     300             :     ScBroadcastArea      *pUpdateChain;
     301             :     ScBroadcastArea      *pEOUpdateChain;
     302             :     sal_uLong             nInBulkBroadcast;
     303             : 
     304             :     static inline SCSIZE ComputeSlotOffset( const ScAddress& rAddress );
     305             :     static void          ComputeAreaPoints( const ScRange& rRange,
     306             :                                             SCSIZE& nStart, SCSIZE& nEnd,
     307             :                                             SCSIZE& nRowBreak );
     308             : 
     309             : public:
     310             :                         ScBroadcastAreaSlotMachine( ScDocument* pDoc );
     311             :                         ~ScBroadcastAreaSlotMachine();
     312             :     void StartListeningArea(
     313             :         const ScRange& rRange, bool bGroupListening, SvtListener* pListener );
     314             : 
     315             :     void EndListeningArea(
     316             :         const ScRange& rRange, bool bGroupListening, SvtListener* pListener );
     317             : 
     318             :     bool AreaBroadcast( const ScRange& rRange, sal_uLong nHint );
     319             :     bool                AreaBroadcast( const ScHint& rHint ) const;
     320             :         // return: at least one broadcast occurred
     321             :     void                DelBroadcastAreasInRange( const ScRange& rRange );
     322             :     void                UpdateBroadcastAreas( UpdateRefMode eUpdateRefMode,
     323             :                                             const ScRange& rRange,
     324             :                                             SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
     325             :     void                EnterBulkBroadcast();
     326             :     void                LeaveBulkBroadcast();
     327             :     bool                InsertBulkArea( const ScBroadcastArea* p );
     328             : 
     329             :     void InsertBulkGroupArea( ScBroadcastArea* pArea, const ScRange& rRange );
     330             :     void BulkBroadcastGroupAreas();
     331             : 
     332             :     /// @return: how many removed
     333             :     size_t              RemoveBulkArea( const ScBroadcastArea* p );
     334             :     inline ScBroadcastArea* GetUpdateChain() const { return pUpdateChain; }
     335          49 :     inline void SetUpdateChain( ScBroadcastArea* p ) { pUpdateChain = p; }
     336          49 :     inline ScBroadcastArea* GetEOUpdateChain() const { return pEOUpdateChain; }
     337          49 :     inline void SetEOUpdateChain( ScBroadcastArea* p ) { pEOUpdateChain = p; }
     338         651 :     inline bool IsInBulkBroadcast() const { return nInBulkBroadcast > 0; }
     339             : 
     340             :     // only for ScBroadcastAreaSlot
     341             :     void                PushAreaToBeErased( ScBroadcastAreaSlot* pSlot,
     342             :                                             ScBroadcastAreas::iterator& rIter );
     343             :     // only for ScBroadcastAreaSlot
     344             :     void                FinallyEraseAreas( ScBroadcastAreaSlot* pSlot );
     345             : 
     346             :     std::vector<sc::AreaListener> GetAllListeners(
     347             :         const ScRange& rRange, sc::AreaOverlapType eType,
     348             :         sc::ListenerGroupType eGroup = sc::ListenerBoth );
     349             : 
     350             : #if DEBUG_AREA_BROADCASTER
     351             :     void Dump() const;
     352             : #endif
     353             : };
     354             : 
     355             : class ScBulkBroadcast
     356             : {
     357             :     ScBroadcastAreaSlotMachine* pBASM;
     358             : public:
     359       50990 :     explicit ScBulkBroadcast( ScBroadcastAreaSlotMachine* p ) : pBASM(p)
     360             :     {
     361       50990 :         if (pBASM)
     362       50923 :             pBASM->EnterBulkBroadcast();
     363       50990 :     }
     364       50990 :     ~ScBulkBroadcast()
     365             :     {
     366       50990 :         if (pBASM)
     367       50923 :             pBASM->LeaveBulkBroadcast();
     368       50990 :     }
     369             :     void LeaveBulkBroadcast()
     370             :     {
     371             :         if (pBASM)
     372             :         {
     373             :             pBASM->LeaveBulkBroadcast();
     374             :             pBASM = NULL;
     375             :         }
     376             :     }
     377             : };
     378             : 
     379             : #endif
     380             : 
     381             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11