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 : #include <frame.hxx>
21 : #include <hintids.hxx>
22 : #include <hints.hxx>
23 : #include <swcache.hxx>
24 : #include <swfntcch.hxx>
25 :
26 : static SwClientIter* pClientIters = 0;
27 :
28 11237609 : TYPEINIT0( SwClient );
29 :
30 12899818 : SwClient::SwClient( SwModify* pToRegisterIn )
31 12899818 : : pLeft( 0 ), pRight( 0 ), pRegisteredIn( 0 ), mbIsAllowedToBeRemovedInModifyCall( false )
32 : {
33 12899818 : if(pToRegisterIn)
34 : // connect to SwModify
35 1403160 : pToRegisterIn->Add(this);
36 12899818 : }
37 :
38 206571 : void SwClient::CheckRegistration( const SfxPoolItem* pOld, const SfxPoolItem* )
39 : {
40 : // this method only handles notification about dying SwModify objects
41 206571 : if( (!pOld || pOld->Which() != RES_OBJECTDYING) )
42 195873 : return;
43 :
44 10698 : const SwPtrMsgPoolItem* pDead = static_cast<const SwPtrMsgPoolItem*>(pOld);
45 10698 : if(pDead && pDead->pObject == pRegisteredIn)
46 : {
47 : // I've got a notification from the object I know
48 10698 : SwModify* pAbove = const_cast<SwModify*>(pRegisteredIn->GetRegisteredIn());
49 10698 : if(pAbove)
50 : {
51 : // if the dying object itself was listening at an SwModify, I take over
52 : // adding myself to pAbove will automatically remove me from my current pRegisteredIn
53 41 : pAbove->Add(this);
54 41 : return;
55 : }
56 : // destroy connection
57 10657 : pRegisteredIn->Remove(this);
58 : }
59 : }
60 :
61 167108 : void SwClient::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
62 : {
63 167108 : CheckRegistration( pOldValue, pNewValue );
64 167108 : }
65 :
66 1500 : void SwClient::SwClientNotify( const SwModify&, const SfxHint& )
67 : {
68 1500 : }
69 :
70 16391129 : SwClient::~SwClient()
71 : {
72 : OSL_ENSURE( !pRegisteredIn || pRegisteredIn->GetDepends(), "SwModify still known, but Client already disconnected!" );
73 16391129 : if( pRegisteredIn && pRegisteredIn->GetDepends() )
74 : // still connected
75 1195609 : pRegisteredIn->Remove( this );
76 16391129 : }
77 :
78 5320 : bool SwClient::GetInfo( SfxPoolItem& ) const
79 : {
80 5320 : return true;
81 : }
82 :
83 199008 : SwModify::SwModify()
84 199008 : : SwClient(0), pRoot(0)
85 : {
86 199008 : bModifyLocked = false;
87 199008 : bLockClientList = false;
88 199008 : bInDocDTOR = false;
89 199008 : bInCache = false;
90 199008 : bInSwFntCache = false;
91 199008 : }
92 :
93 1052290 : SwModify::SwModify( SwModify* pToRegisterIn )
94 1052290 : : SwClient( pToRegisterIn ), pRoot( 0 )
95 : {
96 1052290 : bModifyLocked = false;
97 1052290 : bLockClientList = false;
98 1052290 : bInDocDTOR = false;
99 1052290 : bInCache = false;
100 1052290 : bInSwFntCache = false;
101 1052290 : }
102 :
103 2501480 : SwModify::~SwModify()
104 : {
105 : OSL_ENSURE( !IsModifyLocked(), "Modify destroyed but locked." );
106 :
107 1250740 : if ( IsInCache() )
108 28036 : SwFrm::GetCache().Delete( this );
109 :
110 1250740 : if ( IsInSwFntCache() )
111 0 : pSwFontCache->Delete( this );
112 :
113 1250740 : if( pRoot )
114 : {
115 : // there are depending objects
116 558329 : if( IsInDocDTOR() )
117 : {
118 : // If the document gets destroyed anyway, just tell clients to
119 : // forget me so that they don't try to get removed from my list
120 : // later when they also get destroyed
121 250 : SwClientIter aIter( *this );
122 250 : SwClient* p = aIter.GoStart();
123 1155 : while ( p )
124 : {
125 655 : p->pRegisteredIn = 0;
126 655 : p = ++aIter;
127 250 : }
128 : }
129 : else
130 : {
131 : // notify all clients that they shall remove themselves
132 558079 : SwPtrMsgPoolItem aDyObject( RES_OBJECTDYING, this );
133 558079 : NotifyClients( &aDyObject, &aDyObject );
134 :
135 : // remove all clients that have not done themselves
136 : // mba: possibly a hotfix for forgotten base class calls?!
137 1126664 : while( pRoot )
138 568585 : pRoot->CheckRegistration( &aDyObject, &aDyObject );
139 : }
140 : }
141 1250740 : }
142 :
143 165715 : void SwModify::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
144 : {
145 165715 : NotifyClients( pOldValue, pNewValue );
146 165715 : }
147 :
148 3162221 : void SwModify::NotifyClients( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
149 : {
150 3162221 : if ( IsInCache() || IsInSwFntCache() )
151 : {
152 : const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
153 53904 : pNewValue ? pNewValue->Which() : 0;
154 53904 : CheckCaching( nWhich );
155 : }
156 :
157 3162221 : if ( !pRoot || IsModifyLocked() )
158 4843032 : return;
159 :
160 1481410 : LockModify();
161 :
162 : // mba: WTF?!
163 1481410 : if( !pOldValue )
164 : {
165 149030 : bLockClientList = true;
166 : }
167 : else
168 : {
169 1332380 : switch( pOldValue->Which() )
170 : {
171 : case RES_OBJECTDYING:
172 : case RES_REMOVE_UNO_OBJECT:
173 560430 : bLockClientList = ((SwPtrMsgPoolItem*)pOldValue)->pObject != this;
174 560430 : break;
175 :
176 : default:
177 771950 : bLockClientList = true;
178 : }
179 : }
180 :
181 1481410 : ModifyBroadcast( pOldValue, pNewValue );
182 1481410 : bLockClientList = false;
183 1481410 : UnlockModify();
184 : }
185 :
186 283042 : bool SwModify::GetInfo( SfxPoolItem& rInfo ) const
187 : {
188 283042 : bool bRet = true; // means: continue with next
189 :
190 283042 : if( pRoot )
191 : {
192 128513 : SwClientIter aIter( *(SwModify*)this );
193 :
194 128513 : SwClient* pLast = aIter.GoStart();
195 128513 : if( pLast )
196 : {
197 128513 : while( ( bRet = pLast->GetInfo( rInfo ) ) &&
198 : 0 != ( pLast = ++aIter ) )
199 : ;
200 128513 : }
201 : }
202 :
203 283042 : return bRet;
204 : }
205 :
206 2365631 : void SwModify::Add( SwClient* pDepend )
207 : {
208 : OSL_ENSURE( !bLockClientList, "Client inserted while in Modify" );
209 :
210 2365631 : if(pDepend->pRegisteredIn != this )
211 : {
212 : #if OSL_DEBUG_LEVEL > 0
213 : SwClientIter* pTmp = pClientIters;
214 : while( pTmp )
215 : {
216 : OSL_ENSURE( &pTmp->GetModify() != pRoot, "Client added to active ClientIter" );
217 : pTmp = pTmp->pNxtIter;
218 : }
219 : #endif
220 : // deregister new client in case it is already registered elsewhere
221 2203150 : if( pDepend->pRegisteredIn != 0 )
222 151902 : pDepend->pRegisteredIn->Remove( pDepend );
223 :
224 2203150 : if( !pRoot )
225 : {
226 : // first client added
227 1143095 : pRoot = pDepend;
228 1143095 : pRoot->pLeft = 0;
229 1143095 : pRoot->pRight = 0;
230 : }
231 : else
232 : {
233 : // append client
234 1060055 : pDepend->pRight = pRoot->pRight;
235 1060055 : pRoot->pRight = pDepend;
236 1060055 : pDepend->pLeft = pRoot;
237 1060055 : if( pDepend->pRight )
238 778452 : pDepend->pRight->pLeft = pDepend;
239 : }
240 :
241 : // connect client to me
242 2203150 : pDepend->pRegisteredIn = this;
243 : }
244 2365631 : }
245 :
246 2202135 : SwClient* SwModify::Remove( SwClient* pDepend )
247 : {
248 2202135 : if ( bInDocDTOR )
249 0 : return 0;
250 :
251 : OSL_ENSURE( !bLockClientList || pDepend->mbIsAllowedToBeRemovedInModifyCall, "SwClient shall be removed in Modify call!" );
252 :
253 2202135 : if( pDepend->pRegisteredIn == this )
254 : {
255 : // SwClient is my listener
256 : // remove it from my list
257 2202135 : SwClient* pR = pDepend->pRight;
258 2202135 : SwClient* pL = pDepend->pLeft;
259 2202135 : if( pRoot == pDepend )
260 1374258 : pRoot = pL ? pL : pR;
261 :
262 2202135 : if( pL )
263 827877 : pL->pRight = pR;
264 2202135 : if( pR )
265 819701 : pR->pLeft = pL;
266 :
267 : // update ClientIters
268 2202135 : SwClientIter* pTmp = pClientIters;
269 5011596 : while( pTmp )
270 : {
271 607326 : if( pTmp->pAct == pDepend || pTmp->pDelNext == pDepend )
272 : {
273 : // if object being removed is the current or next object in an
274 : // iterator, advance this iterator
275 556591 : pTmp->pDelNext = pR;
276 : }
277 607326 : pTmp = pTmp->pNxtIter;
278 : }
279 :
280 2202135 : pDepend->pLeft = 0;
281 2202135 : pDepend->pRight = 0;
282 : }
283 : else
284 : {
285 : OSL_FAIL( "SwModify::Remove(): could not find pDepend" );
286 : }
287 :
288 : // disconnect client from me
289 2202135 : pDepend->pRegisteredIn = 0;
290 2202135 : return pDepend;
291 : }
292 :
293 58672 : void SwModify::CheckCaching( const sal_uInt16 nWhich )
294 : {
295 58672 : if( isCHRATR( nWhich ) )
296 : {
297 0 : SetInSwFntCache( false );
298 : }
299 : else
300 : {
301 58672 : switch( nWhich )
302 : {
303 : case RES_OBJECTDYING:
304 : case RES_FMT_CHG:
305 : case RES_ATTRSET_CHG:
306 40852 : SetInSwFntCache( false );
307 : // fall through
308 : case RES_UL_SPACE:
309 : case RES_LR_SPACE:
310 : case RES_BOX:
311 : case RES_SHADOW:
312 : case RES_FRM_SIZE:
313 : case RES_KEEP:
314 : case RES_BREAK:
315 41972 : if( IsInCache() )
316 : {
317 33857 : SwFrm::GetCache().Delete( this );
318 33857 : SetInCache( false );
319 : }
320 41972 : break;
321 : }
322 : }
323 58672 : }
324 :
325 11760 : void SwModify::CallSwClientNotify( const SfxHint& rHint ) const
326 : {
327 11760 : SwClientIter aIter(*this);
328 11760 : SwClient* pClient = aIter.GoStart();
329 25138 : while( pClient )
330 : {
331 1618 : pClient->SwClientNotify( *this, rHint );
332 1618 : pClient = ++aIter;
333 11760 : }
334 11760 : }
335 :
336 1498850 : void SwModify::ModifyBroadcast( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue, TypeId nType )
337 : {
338 1498850 : SwClientIter aIter( *this );
339 1498850 : SwClient* pClient = aIter.First( nType );
340 5483466 : while( pClient )
341 : {
342 2485766 : pClient->Modify( pOldValue, pNewValue );
343 2485766 : pClient = aIter.Next();
344 1498850 : }
345 1498850 : }
346 :
347 273366 : SwDepend::SwDepend( SwClient* pTellHim, SwModify* pDepend )
348 273366 : : SwClient( pDepend )
349 : {
350 273366 : pToTell = pTellHim;
351 273366 : }
352 :
353 1984 : void SwDepend::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
354 : {
355 1984 : if( pNewValue && pNewValue->Which() == RES_OBJECTDYING )
356 130 : CheckRegistration(pOldValue,pNewValue);
357 1854 : else if( pToTell )
358 1854 : pToTell->ModifyNotification(pOldValue, pNewValue);
359 1984 : }
360 :
361 0 : void SwDepend::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
362 : {
363 0 : if ( pToTell )
364 0 : pToTell->SwClientNotifyCall( rMod, rHint );
365 0 : }
366 :
367 8 : bool SwDepend::GetInfo( SfxPoolItem& rInfo ) const
368 : {
369 8 : return pToTell ? pToTell->GetInfo( rInfo ) : true;
370 : }
371 :
372 3776098 : SwClientIter::SwClientIter( const SwModify& rModify )
373 : : rRoot(rModify)
374 : , pNxtIter(NULL)
375 3776098 : , aSrchId(0)
376 : {
377 3776098 : if( pClientIters )
378 : {
379 : // append to list of ClientIters
380 440947 : SwClientIter* pTmp = pClientIters;
381 1208696 : while( pTmp->pNxtIter )
382 326802 : pTmp = pTmp->pNxtIter;
383 440947 : pTmp->pNxtIter = this;
384 : }
385 : else
386 3335151 : pClientIters = this;
387 :
388 3776098 : pAct = const_cast<SwClient*>(rRoot.GetDepends());
389 3776098 : pDelNext = pAct;
390 3776098 : }
391 :
392 3776098 : SwClientIter::~SwClientIter()
393 : {
394 3776098 : if( pClientIters )
395 : {
396 : // reorganize list of ClientIters
397 3776098 : if( pClientIters == this )
398 3335151 : pClientIters = pNxtIter;
399 : else
400 : {
401 440947 : SwClientIter* pTmp = pClientIters;
402 1208696 : while( pTmp->pNxtIter != this )
403 326802 : if( 0 == ( pTmp = pTmp->pNxtIter ) )
404 : {
405 : OSL_ENSURE( this, "Lost my pointer" );
406 0 : return ;
407 : }
408 440947 : pTmp->pNxtIter = pNxtIter;
409 : }
410 : }
411 7552196 : }
412 :
413 517360 : SwClient* SwClientIter::operator++()
414 : {
415 517360 : if( pDelNext == pAct )
416 : {
417 517326 : pAct = pAct->pRight;
418 517326 : pDelNext = pAct;
419 : }
420 : else
421 34 : pAct = pDelNext;
422 517360 : return pAct;
423 : }
424 :
425 3771966 : SwClient* SwClientIter::GoStart()
426 : {
427 3771966 : pAct = const_cast<SwClient*>(rRoot.GetDepends());
428 3771966 : if( pAct )
429 : {
430 7006408 : while( pAct->pLeft )
431 0 : pAct = pAct->pLeft;
432 : }
433 3771966 : pDelNext = pAct;
434 3771966 : return pAct;
435 : }
436 :
437 696 : SwClient* SwClientIter::GoEnd()
438 : {
439 696 : pAct = pDelNext;
440 696 : if( !pAct )
441 696 : pAct = const_cast<SwClient*>(rRoot.GetDepends());
442 696 : if( pAct )
443 : {
444 0 : while( pAct->pRight )
445 0 : pAct = pAct->pRight;
446 : }
447 696 : pDelNext = pAct;
448 696 : return pAct;
449 : }
450 :
451 3611061 : SwClient* SwClientIter::First( TypeId nType )
452 : {
453 3611061 : aSrchId = nType;
454 3611061 : GoStart();
455 3611061 : if( pAct )
456 1464915 : do {
457 4682028 : if( pAct->IsA( aSrchId ) )
458 3217113 : break;
459 :
460 1464915 : if( pDelNext == pAct )
461 : {
462 1464915 : pAct = pAct->pRight;
463 1464915 : pDelNext = pAct;
464 : }
465 : else
466 0 : pAct = pDelNext;
467 : } while( pAct );
468 3611061 : return pAct;
469 : }
470 :
471 696 : SwClient* SwClientIter::Last( TypeId nType )
472 : {
473 696 : aSrchId = nType;
474 696 : GoEnd();
475 696 : if( pAct )
476 0 : do {
477 0 : if( pAct->IsA( aSrchId ) )
478 0 : break;
479 :
480 0 : if( pDelNext == pAct )
481 0 : pAct = pAct->pLeft;
482 : else
483 0 : pAct = pDelNext->pLeft;
484 0 : pDelNext = pAct;
485 : } while( pAct );
486 696 : return pAct;
487 : }
488 :
489 3223769 : SwClient* SwClientIter::Next()
490 : {
491 2084969 : do {
492 3223769 : if( pDelNext == pAct )
493 : {
494 2667264 : pAct = pAct->pRight;
495 2667264 : pDelNext = pAct;
496 : }
497 : else
498 556505 : pAct = pDelNext;
499 :
500 3223769 : if( pAct && pAct->IsA( aSrchId ) )
501 1138800 : break;
502 : } while( pAct );
503 3017946 : return pAct;
504 : }
505 :
506 0 : SwClient* SwClientIter::Previous()
507 : {
508 0 : do {
509 0 : if( pDelNext == pAct )
510 0 : pAct = pAct->pLeft;
511 : else
512 0 : pAct = pDelNext->pLeft;
513 0 : pDelNext = pAct;
514 :
515 0 : if( pAct && pAct->IsA( aSrchId ) )
516 0 : break;
517 : } while( pAct );
518 0 : return pAct;
519 270 : }
520 :
521 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|