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