xref: /AOO41X/main/sc/source/core/inc/bcaslot.hxx (revision d3e0dd8eb215533c15e891ee35bd141abe9397ee)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef SC_BCASLOT_HXX
25 #define SC_BCASLOT_HXX
26 
27 #include <set>
28 #include <hash_set>
29 #include <functional>
30 #include <svl/broadcast.hxx>
31 #include <svl/svarray.hxx>
32 
33 #include "global.hxx"
34 #include "brdcst.hxx"
35 
36 /**
37     Used in a Unique Associative Container.
38  */
39 
40 class ScBroadcastArea
41 {
42 private:
43     ScBroadcastArea*    pUpdateChainNext;
44     SvtBroadcaster      aBroadcaster;
45     ScRange             aRange;
46     sal_uLong               nRefCount;
47     sal_Bool                bInUpdateChain;
48 
49 public:
ScBroadcastArea(const ScRange & rRange)50             ScBroadcastArea( const ScRange& rRange )
51                 : pUpdateChainNext( NULL ), aRange( rRange ),
52                 nRefCount( 0 ), bInUpdateChain( sal_False ) {}
GetBroadcaster()53     inline SvtBroadcaster&       GetBroadcaster()       { return aBroadcaster; }
GetBroadcaster() const54     inline const SvtBroadcaster& GetBroadcaster() const { return aBroadcaster; }
UpdateRange(const ScRange & rNewRange)55     inline void         UpdateRange( const ScRange& rNewRange )
56                             { aRange = rNewRange; }
GetRange() const57     inline const ScRange&   GetRange() const { return aRange; }
GetStart() const58     inline const ScAddress& GetStart() const { return aRange.aStart; }
GetEnd() const59     inline const ScAddress& GetEnd() const { return aRange.aEnd; }
IncRef()60     inline void         IncRef() { ++nRefCount; }
DecRef()61     inline sal_uLong        DecRef() { return nRefCount ? --nRefCount : 0; }
GetRef()62     inline sal_uLong        GetRef() { return nRefCount; }
GetUpdateChainNext() const63     inline ScBroadcastArea* GetUpdateChainNext() const { return pUpdateChainNext; }
SetUpdateChainNext(ScBroadcastArea * p)64     inline void         SetUpdateChainNext( ScBroadcastArea* p ) { pUpdateChainNext = p; }
IsInUpdateChain() const65     inline sal_Bool         IsInUpdateChain() const { return bInUpdateChain; }
SetInUpdateChain(sal_Bool b)66     inline void         SetInUpdateChain( sal_Bool b ) { bInUpdateChain = b; }
67 
68     /** Equalness of this or range. */
69     inline  bool        operator==( const ScBroadcastArea & rArea ) const;
70 };
71 
operator ==(const ScBroadcastArea & rArea) const72 inline bool ScBroadcastArea::operator==( const ScBroadcastArea & rArea ) const
73 {
74     return aRange == rArea.aRange;
75 }
76 
77 //=============================================================================
78 
79 struct ScBroadcastAreaHash
80 {
operator ()ScBroadcastAreaHash81     size_t operator()( const ScBroadcastArea* p ) const
82     {
83         return p->GetRange().hashArea();
84     }
85 };
86 
87 struct ScBroadcastAreaEqual
88 {
operator ()ScBroadcastAreaEqual89     bool operator()( const ScBroadcastArea* p1, const ScBroadcastArea* p2) const
90     {
91         return *p1 == *p2;
92     }
93 };
94 
95 typedef ::std::hash_set< ScBroadcastArea*, ScBroadcastAreaHash, ScBroadcastAreaEqual > ScBroadcastAreas;
96 
97 //=============================================================================
98 
99 struct ScBroadcastAreaBulkHash
100 {
operator ()ScBroadcastAreaBulkHash101     size_t operator()( const ScBroadcastArea* p ) const
102     {
103         return reinterpret_cast<size_t>(p);
104     }
105 };
106 
107 struct ScBroadcastAreaBulkEqual
108 {
operator ()ScBroadcastAreaBulkEqual109     bool operator()( const ScBroadcastArea* p1, const ScBroadcastArea* p2) const
110     {
111         return p1 == p2;
112     }
113 };
114 
115 typedef ::std::hash_set< const ScBroadcastArea*, ScBroadcastAreaBulkHash,
116         ScBroadcastAreaBulkEqual > ScBroadcastAreasBulk;
117 
118 //=============================================================================
119 
120 class ScBroadcastAreaSlotMachine;
121 
122 /// Collection of BroadcastAreas
123 class ScBroadcastAreaSlot
124 {
125 private:
126     ScBroadcastAreas    aBroadcastAreaTbl;
127     mutable ScBroadcastArea aTmpSeekBroadcastArea;      // for FindBroadcastArea()
128     ScDocument*         pDoc;
129     ScBroadcastAreaSlotMachine* pBASM;
130 
131     ScBroadcastAreas::const_iterator  FindBroadcastArea( const ScRange& rRange ) const;
132 
133     /**
134         More hypothetical (memory would probably be doomed anyway) check
135         whether there would be an overflow when adding an area, setting the
136         proper state if so.
137 
138         @return sal_True if a HardRecalcState is effective and area is not to be
139         added.
140       */
141     bool                CheckHardRecalcStateCondition() const;
142 
143 public:
144                         ScBroadcastAreaSlot( ScDocument* pDoc,
145                                         ScBroadcastAreaSlotMachine* pBASM );
146                         ~ScBroadcastAreaSlot();
GetBroadcastAreas() const147     const ScBroadcastAreas& GetBroadcastAreas() const
148                                             { return aBroadcastAreaTbl; }
149 
150     /**
151         Only here new ScBroadcastArea objects are created, prevention of dupes.
152 
153         @param rpArea
154             If NULL, a new ScBroadcastArea is created and assigned ton the
155             reference if a matching area wasn't found. If a matching area was
156             found, that is assigned. In any case, the SvtListener is added to
157             the broadcaster.
158 
159             If not NULL then no listeners are startet, only the area is
160             inserted and the reference count incremented. Effectively the same
161             as InsertListeningArea(), so use that instead.
162 
163         @return
164             sal_True if rpArea passed was NULL and ScBroadcastArea is newly
165             created.
166      */
167     bool                StartListeningArea( const ScRange& rRange,
168                                             SvtListener* pListener,
169                                             ScBroadcastArea*& rpArea );
170 
171     /**
172         Insert a ScBroadcastArea obtained via StartListeningArea() to
173         subsequent slots.
174      */
175     void                InsertListeningArea( ScBroadcastArea* pArea );
176 
177     void                EndListeningArea( const ScRange& rRange,
178                                             SvtListener* pListener,
179                                             ScBroadcastArea*& rpArea );
180     sal_Bool                AreaBroadcast( const ScHint& rHint ) const;
181     /// @return sal_True if at least one broadcast occurred.
182     sal_Bool                AreaBroadcastInRange( const ScRange& rRange,
183                                               const ScHint& rHint ) const;
184     void                DelBroadcastAreasInRange( const ScRange& rRange );
185     void                UpdateRemove( UpdateRefMode eUpdateRefMode,
186                                         const ScRange& rRange,
187                                         SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
188     void                UpdateRemoveArea( ScBroadcastArea* pArea );
189     void                UpdateInsert( ScBroadcastArea* pArea );
190 };
191 
192 
193 /**
194     BroadcastAreaSlots and their management, once per document.
195  */
196 
197 class  ScBroadcastAreaSlotMachine
198 {
199 private:
200 
201     /**
202         Slot offset arrangement of columns and rows, once per sheet.
203 
204         +---+---+
205         | 0 | 3 |
206         +---+---+
207         | 1 | 4 |
208         +---+---+
209         | 2 | 5 |
210         +---+---+
211      */
212 
213     class TableSlots
214     {
215         public:
216                                             TableSlots();
217                                             ~TableSlots();
getSlots()218             inline ScBroadcastAreaSlot**    getSlots() { return ppSlots; }
219 
220             /**
221                 Obtain slot pointer, no check on validity! It is assumed that
222                 all calls are made with the results of ComputeSlotOffset(),
223                 ComputeAreaPoints() and ComputeNextSlot()
224               */
getAreaSlot(SCSIZE nOff)225             inline ScBroadcastAreaSlot*     getAreaSlot( SCSIZE nOff ) { return *(ppSlots + nOff); }
226 
227         private:
228             ScBroadcastAreaSlot**   ppSlots;
229 
230             // prevent usage
231             TableSlots( const TableSlots& );
232             TableSlots& operator=( const TableSlots& );
233     };
234 
235     typedef ::std::map< SCTAB, TableSlots* > TableSlotsMap;
236 
237 private:
238     ScBroadcastAreasBulk  aBulkBroadcastAreas;
239     TableSlotsMap         aTableSlotsMap;
240     SvtBroadcaster       *pBCAlways;             // for the RC_ALWAYS special range
241     ScDocument           *pDoc;
242     ScBroadcastArea      *pUpdateChain;
243     ScBroadcastArea      *pEOUpdateChain;
244     sal_uLong                 nInBulkBroadcast;
245 
246     inline SCSIZE       ComputeSlotOffset( const ScAddress& rAddress ) const;
247     void                ComputeAreaPoints( const ScRange& rRange,
248                                             SCSIZE& nStart, SCSIZE& nEnd,
249                                             SCSIZE& nRowBreak ) const;
250 
251 public:
252                         ScBroadcastAreaSlotMachine( ScDocument* pDoc );
253                         ~ScBroadcastAreaSlotMachine();
254     void                StartListeningArea( const ScRange& rRange,
255                                             SvtListener* pListener );
256     void                EndListeningArea( const ScRange& rRange,
257                                             SvtListener* pListener );
258     sal_Bool                AreaBroadcast( const ScHint& rHint ) const;
259         // return: at least one broadcast occurred
260     sal_Bool                AreaBroadcastInRange( const ScRange& rRange, const ScHint& rHint ) const;
261     void                DelBroadcastAreasInRange( const ScRange& rRange );
262     void                UpdateBroadcastAreas( UpdateRefMode eUpdateRefMode,
263                                             const ScRange& rRange,
264                                             SCsCOL nDx, SCsROW nDy, SCsTAB nDz );
265     void                EnterBulkBroadcast();
266     void                LeaveBulkBroadcast();
267     bool                InsertBulkArea( const ScBroadcastArea* p );
268     /// @return: how many removed
269     size_t              RemoveBulkArea( const ScBroadcastArea* p );
GetUpdateChain() const270     inline ScBroadcastArea* GetUpdateChain() const { return pUpdateChain; }
SetUpdateChain(ScBroadcastArea * p)271     inline void SetUpdateChain( ScBroadcastArea* p ) { pUpdateChain = p; }
GetEOUpdateChain() const272     inline ScBroadcastArea* GetEOUpdateChain() const { return pEOUpdateChain; }
SetEOUpdateChain(ScBroadcastArea * p)273     inline void SetEOUpdateChain( ScBroadcastArea* p ) { pEOUpdateChain = p; }
IsInBulkBroadcast() const274     inline bool IsInBulkBroadcast() const { return nInBulkBroadcast > 0; }
275 };
276 
277 
278 class ScBulkBroadcast
279 {
280     ScBroadcastAreaSlotMachine* pBASM;
281 public:
ScBulkBroadcast(ScBroadcastAreaSlotMachine * p)282     explicit ScBulkBroadcast( ScBroadcastAreaSlotMachine* p ) : pBASM(p)
283     {
284         if (pBASM)
285             pBASM->EnterBulkBroadcast();
286     }
~ScBulkBroadcast()287     ~ScBulkBroadcast()
288     {
289         if (pBASM)
290             pBASM->LeaveBulkBroadcast();
291     }
LeaveBulkBroadcast()292     void LeaveBulkBroadcast()
293     {
294         if (pBASM)
295         {
296             pBASM->LeaveBulkBroadcast();
297             pBASM = NULL;
298         }
299     }
300 };
301 
302 #endif
303