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