xref: /trunk/main/sc/source/core/inc/bcaslot.hxx (revision 6d3b264b)
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