Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <frame.hxx>
30 : : #include <hintids.hxx> // contains RES_.. IDs
31 : : #include <hints.hxx>
32 : : #include <swcache.hxx> // mba: get rid of that dependency
33 : : #include <swfntcch.hxx> // mba: get rid of that dependency
34 : :
35 : : static SwClientIter* pClientIters = 0;
36 : :
37 [ + + ]: 1912622 : TYPEINIT0( SwClient );
38 : :
39 : : // ----------
40 : : // SwClient
41 : : // ----------
42 : :
43 : 501817 : SwClient::SwClient( SwModify* pToRegisterIn )
44 : 501817 : : pLeft( 0 ), pRight( 0 ), pRegisteredIn( 0 ), mbIsAllowedToBeRemovedInModifyCall( false )
45 : : {
46 [ + + ]: 501817 : if(pToRegisterIn)
47 : : // connect to SwModify
48 [ + - ]: 117948 : pToRegisterIn->Add(this);
49 : 501817 : }
50 : :
51 : 9394 : void SwClient::CheckRegistration( const SfxPoolItem* pOld, const SfxPoolItem* )
52 : : {
53 : : // this method only handles notification about dying SwModify objects
54 [ + + ][ + + ]: 9394 : if( (!pOld || pOld->Which() != RES_OBJECTDYING) )
[ + + ]
55 : 7950 : return;
56 : :
57 : 1444 : const SwPtrMsgPoolItem* pDead = static_cast<const SwPtrMsgPoolItem*>(pOld);
58 [ + - ][ + - ]: 1444 : if(pDead && pDead->pObject == pRegisteredIn)
59 : : {
60 : : // I've got a notification from the object I know
61 : 1444 : SwModify* pAbove = const_cast<SwModify*>(pRegisteredIn->GetRegisteredIn());
62 [ + + ]: 1444 : if(pAbove)
63 : : {
64 : : // if the dying object itself was listening at an SwModify, I take over
65 : : // adding myself to pAbove will automatically remove me from my current pRegisteredIn
66 : 40 : pAbove->Add(this);
67 : 40 : return;
68 : : }
69 : : // destroy connection
70 : 9394 : pRegisteredIn->Remove(this);
71 : : }
72 : : }
73 : :
74 : 6639 : void SwClient::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
75 : : {
76 : 6639 : CheckRegistration( pOldValue, pNewValue );
77 : 6639 : }
78 : :
79 : 525 : void SwClient::SwClientNotify( const SwModify&, const SfxHint& )
80 : : {
81 : 525 : }
82 : :
83 : 573735 : SwClient::~SwClient()
84 : : {
85 : : OSL_ENSURE( !pRegisteredIn || pRegisteredIn->GetDepends(), "SwModify still known, but Client already disconnected!" );
86 [ + + ][ + - ]: 573735 : if( pRegisteredIn && pRegisteredIn->GetDepends() )
[ + + ]
87 : : // still connected
88 [ + - ]: 124725 : pRegisteredIn->Remove( this );
89 [ - + ]: 573735 : }
90 : :
91 : 12 : sal_Bool SwClient::GetInfo( SfxPoolItem& ) const
92 : : {
93 : 12 : return sal_True;
94 : : }
95 : :
96 : : // ----------
97 : : // SwModify
98 : : // ----------
99 : :
100 : 24783 : SwModify::SwModify()
101 : 24783 : : SwClient(0), pRoot(0)
102 : : {
103 : 24783 : bModifyLocked = sal_False;
104 : 24783 : bLockClientList = sal_False;
105 : 24783 : bInDocDTOR = sal_False;
106 : 24783 : bInCache = sal_False;
107 : 24783 : bInSwFntCache = sal_False;
108 : 24783 : }
109 : :
110 : 177853 : SwModify::SwModify( SwModify* pToRegisterIn )
111 : 177853 : : SwClient( pToRegisterIn ), pRoot( 0 )
112 : : {
113 : 177853 : bModifyLocked = sal_False;
114 : 177853 : bLockClientList = sal_False;
115 : 177853 : bInDocDTOR = sal_False;
116 : 177853 : bInCache = sal_False;
117 : 177853 : bInSwFntCache = sal_False;
118 : 177853 : }
119 : :
120 : 196372 : SwModify::~SwModify()
121 : : {
122 : : OSL_ENSURE( !IsModifyLocked(), "Modify destroyed but locked." );
123 : :
124 [ + + ]: 196372 : if ( IsInCache() )
125 [ + - ]: 4823 : SwFrm::GetCache().Delete( this );
126 : :
127 [ - + ]: 196372 : if ( IsInSwFntCache() )
128 [ # # ]: 0 : pSwFontCache->Delete( this );
129 : :
130 [ + + ]: 196372 : if( pRoot )
131 : : {
132 : : // there are depending objects
133 [ + + ]: 50150 : if( IsInDocDTOR() )
134 : : {
135 : : // If the document gets destroyed anyway, just tell clients to
136 : : // forget me so that they don't try to get removed from my list
137 : : // later when they also get destroyed
138 [ + - ]: 62 : SwClientIter aIter( *this );
139 : 62 : SwClient* p = aIter.GoStart();
140 [ + + ]: 283 : while ( p )
141 : : {
142 : 221 : p->pRegisteredIn = 0;
143 : 221 : p = aIter++;
144 [ + - ]: 62 : }
145 : : }
146 : : else
147 : : {
148 : : // notify all clients that they shall remove themselves
149 [ + - ]: 50088 : SwPtrMsgPoolItem aDyObject( RES_OBJECTDYING, this );
150 [ + - ]: 50088 : NotifyClients( &aDyObject, &aDyObject );
151 : :
152 : : // remove all clients that have not done themselves
153 : : // mba: possibly a hotfix for forgotten base class calls?!
154 [ + + ]: 51384 : while( pRoot )
155 [ + - ][ + - ]: 51384 : pRoot->CheckRegistration( &aDyObject, &aDyObject );
156 : : }
157 : : }
158 [ - + ]: 197830 : }
159 : :
160 : 44885 : void SwModify::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
161 : : {
162 : 44885 : NotifyClients( pOldValue, pNewValue );
163 : 44885 : }
164 : :
165 : 449859 : void SwModify::NotifyClients( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
166 : : {
167 [ + + ][ + + ]: 449859 : if ( IsInCache() || IsInSwFntCache() )
[ + + ]
168 : : {
169 : : const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
170 [ + + ][ + - ]: 17570 : pNewValue ? pNewValue->Which() : 0;
171 : 17570 : CheckCaching( nWhich );
172 : : }
173 : :
174 [ + + ][ + + ]: 449859 : if ( !pRoot || IsModifyLocked() )
[ + + ]
175 : 449859 : return;
176 : :
177 : 183683 : LockModify();
178 : :
179 : : // mba: WTF?!
180 [ + + ]: 183683 : if( !pOldValue )
181 : : {
182 : 23990 : bLockClientList = sal_True;
183 : : }
184 : : else
185 : : {
186 [ + + + ]: 159693 : switch( pOldValue->Which() )
187 : : {
188 : : case RES_OBJECTDYING:
189 : : case RES_REMOVE_UNO_OBJECT:
190 : 50618 : bLockClientList = ((SwPtrMsgPoolItem*)pOldValue)->pObject != this;
191 : 50618 : break;
192 : :
193 : : case RES_FOOTNOTE_DELETED:
194 : : case RES_REFMARK_DELETED:
195 : : case RES_TOXMARK_DELETED:
196 : : case RES_FIELD_DELETED:
197 : 86 : bLockClientList = sal_False;
198 : 86 : break;
199 : :
200 : : default:
201 : 108989 : bLockClientList = sal_True;
202 : : }
203 : : }
204 : :
205 : 183683 : ModifyBroadcast( pOldValue, pNewValue );
206 : 183683 : bLockClientList = sal_False;
207 : 183683 : UnlockModify();
208 : : }
209 : :
210 : 150288 : sal_Bool SwModify::GetInfo( SfxPoolItem& rInfo ) const
211 : : {
212 : 150288 : sal_Bool bRet = sal_True; // means: continue with next
213 : :
214 [ + + ]: 150288 : if( pRoot )
215 : : {
216 [ + - ]: 42591 : SwClientIter aIter( *(SwModify*)this );
217 : :
218 : 42591 : SwClient* pLast = aIter.GoStart();
219 [ + - ]: 42591 : if( pLast )
220 : : {
221 [ + - ][ + + ]: 43379 : while( 0 != ( bRet = pLast->GetInfo( rInfo ) ) &&
[ + + ][ + + ]
222 : : 0 != ( pLast = aIter++ ) )
223 : : ;
224 [ + - ]: 42591 : }
225 : : }
226 : :
227 : 150288 : return bRet;
228 : : }
229 : :
230 : 298000 : void SwModify::Add( SwClient* pDepend )
231 : : {
232 : : OSL_ENSURE( !bLockClientList, "Client inserted while in Modify" );
233 : :
234 [ + + ]: 298000 : if(pDepend->pRegisteredIn != this )
235 : : {
236 : : #if OSL_DEBUG_LEVEL > 0
237 : : SwClientIter* pTmp = pClientIters;
238 : : while( pTmp )
239 : : {
240 : : OSL_ENSURE( &pTmp->GetModify() != pRoot, "Client added to active ClientIter" );
241 : : pTmp = pTmp->pNxtIter;
242 : : }
243 : : #endif
244 : : // deregister new client in case it is already registered elsewhere
245 [ + + ]: 246016 : if( pDepend->pRegisteredIn != 0 )
246 : 11875 : pDepend->pRegisteredIn->Remove( pDepend );
247 : :
248 [ + + ]: 246016 : if( !pRoot )
249 : : {
250 : : // first client added
251 : 130880 : pRoot = pDepend;
252 : 130880 : pRoot->pLeft = 0;
253 : 130880 : pRoot->pRight = 0;
254 : : }
255 : : else
256 : : {
257 : : // append client
258 : 115136 : pDepend->pRight = pRoot->pRight;
259 : 115136 : pRoot->pRight = pDepend;
260 : 115136 : pDepend->pLeft = pRoot;
261 [ + + ]: 115136 : if( pDepend->pRight )
262 : 75191 : pDepend->pRight->pLeft = pDepend;
263 : : }
264 : :
265 : : // connect client to me
266 : 246016 : pDepend->pRegisteredIn = this;
267 : : }
268 : 298000 : }
269 : :
270 : 242615 : SwClient* SwModify::Remove( SwClient* pDepend )
271 : : {
272 [ - + ]: 242615 : if ( bInDocDTOR )
273 : 0 : return 0;
274 : :
275 : : OSL_ENSURE( !bLockClientList || pDepend->mbIsAllowedToBeRemovedInModifyCall, "SwClient shall be removed in Modify call!" );
276 : :
277 [ + - ]: 242615 : if( pDepend->pRegisteredIn == this )
278 : : {
279 : : // SwClient is my listener
280 : : // remove it from my list
281 : 242615 : SwClient* pR = pDepend->pRight;
282 : 242615 : SwClient* pL = pDepend->pLeft;
283 [ + + ]: 242615 : if( pRoot == pDepend )
284 [ - + ]: 166314 : pRoot = pL ? pL : pR;
285 : :
286 [ + + ]: 242615 : if( pL )
287 : 76301 : pL->pRight = pR;
288 [ + + ]: 242615 : if( pR )
289 : 91029 : pR->pLeft = pL;
290 : :
291 : : // update ClientIters
292 : 242615 : SwClientIter* pTmp = pClientIters;
293 [ + + ]: 301259 : while( pTmp )
294 : : {
295 [ + + ][ - + ]: 58644 : if( pTmp->pAct == pDepend || pTmp->pDelNext == pDepend )
296 : : {
297 : : // if object being removed is the current or next object in an
298 : : // iterator, advance this iterator
299 : 53131 : pTmp->pDelNext = pR;
300 : : }
301 : 58644 : pTmp = pTmp->pNxtIter;
302 : : }
303 : :
304 : 242615 : pDepend->pLeft = 0;
305 : 242615 : pDepend->pRight = 0;
306 : : }
307 : : else
308 : : {
309 : : OSL_FAIL( "SwModify::Remove(): could not find pDepend" );
310 : : }
311 : :
312 : : // disconnect client from me
313 : 242615 : pDepend->pRegisteredIn = 0;
314 : 242615 : return pDepend;
315 : : }
316 : :
317 : 18639 : void SwModify::CheckCaching( const sal_uInt16 nWhich )
318 : : {
319 [ - + ]: 18639 : if( isCHRATR( nWhich ) )
320 : : {
321 : 0 : SetInSwFntCache( sal_False );
322 : : }
323 : : else
324 : : {
325 [ + + + ]: 18639 : switch( nWhich )
326 : : {
327 : : case RES_OBJECTDYING:
328 : : case RES_FMT_CHG:
329 : : case RES_ATTRSET_CHG:
330 : 6046 : SetInSwFntCache( sal_False );
331 : :
332 : : case RES_UL_SPACE:
333 : : case RES_LR_SPACE:
334 : : case RES_BOX:
335 : : case RES_SHADOW:
336 : : case RES_FRM_SIZE:
337 : : case RES_KEEP:
338 : : case RES_BREAK:
339 [ + + ]: 6112 : if( IsInCache() )
340 : : {
341 : 4603 : SwFrm::GetCache().Delete( this );
342 : 4603 : SetInCache( sal_False );
343 : : }
344 : 6112 : break;
345 : : }
346 : : }
347 : 18639 : }
348 : :
349 : 1314 : void SwModify::CallSwClientNotify( const SfxHint& rHint ) const
350 : : {
351 [ + - ]: 1314 : SwClientIter aIter(*this);
352 : 1314 : SwClient* pClient = aIter.GoStart();
353 [ + + ]: 1859 : while( pClient )
354 : : {
355 [ + - ]: 545 : pClient->SwClientNotify( *this, rHint );
356 : 545 : pClient = aIter++;
357 [ + - ]: 1314 : }
358 : 1314 : }
359 : :
360 : 184239 : void SwModify::ModifyBroadcast( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue, TypeId nType )
361 : : {
362 [ + - ]: 184239 : SwClientIter aIter( *this );
363 [ + - ]: 184239 : SwClient* pClient = aIter.First( nType );
364 [ + + ]: 536170 : while( pClient )
365 : : {
366 [ + - ]: 351931 : pClient->Modify( pOldValue, pNewValue );
367 [ + - ]: 351931 : pClient = aIter.Next();
368 [ + - ]: 184239 : }
369 : 184239 : }
370 : :
371 : : // ----------
372 : : // SwDepend
373 : : // ----------
374 : :
375 : 49558 : SwDepend::SwDepend( SwClient* pTellHim, SwModify* pDepend )
376 : 49558 : : SwClient( pDepend )
377 : : {
378 : 49558 : pToTell = pTellHim;
379 : 49558 : }
380 : :
381 : 433 : void SwDepend::Modify( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
382 : : {
383 [ + - ][ + + ]: 433 : if( pNewValue && pNewValue->Which() == RES_OBJECTDYING )
[ + + ]
384 : 84 : CheckRegistration(pOldValue,pNewValue);
385 [ + - ]: 349 : else if( pToTell )
386 : 349 : pToTell->ModifyNotification(pOldValue, pNewValue);
387 : 433 : }
388 : :
389 : 0 : void SwDepend::SwClientNotify( const SwModify& rMod, const SfxHint& rHint )
390 : : {
391 [ # # ]: 0 : if ( pToTell )
392 : 0 : pToTell->SwClientNotifyCall( rMod, rHint );
393 : 0 : }
394 : :
395 : 0 : sal_Bool SwDepend::GetInfo( SfxPoolItem& rInfo ) const
396 : : {
397 [ # # ]: 0 : return pToTell ? pToTell->GetInfo( rInfo ) : sal_True;
398 : : }
399 : :
400 : : // ------------
401 : : // SwClientIter
402 : : // ------------
403 : :
404 : 808819 : SwClientIter::SwClientIter( const SwModify& rModify )
405 : 808819 : : rRoot( rModify )
406 : : {
407 : 808819 : pNxtIter = 0;
408 [ + + ]: 808819 : if( pClientIters )
409 : : {
410 : : // append to list of ClientIters
411 : 77383 : SwClientIter* pTmp = pClientIters;
412 [ + + ]: 129569 : while( pTmp->pNxtIter )
413 : 52186 : pTmp = pTmp->pNxtIter;
414 : 77383 : pTmp->pNxtIter = this;
415 : : }
416 : : else
417 : 731436 : pClientIters = this;
418 : :
419 : 808819 : pAct = const_cast<SwClient*>(rRoot.GetDepends());
420 : 808819 : pDelNext = pAct;
421 : 808819 : }
422 : :
423 : :
424 : :
425 : 808819 : SwClientIter::~SwClientIter()
426 : : {
427 [ + - ]: 808819 : if( pClientIters )
428 : : {
429 : : // reorganize list of ClientIters
430 [ + + ]: 808819 : if( pClientIters == this )
431 : 731436 : pClientIters = pNxtIter;
432 : : else
433 : : {
434 : 77383 : SwClientIter* pTmp = pClientIters;
435 [ + + ]: 129569 : while( pTmp->pNxtIter != this )
436 [ - + ]: 52186 : if( 0 == ( pTmp = pTmp->pNxtIter ) )
437 : : {
438 : : OSL_ENSURE( this, "Lost my pointer" );
439 : 0 : return ;
440 : : }
441 : 77383 : pTmp->pNxtIter = pNxtIter;
442 : : }
443 : : }
444 : 808819 : }
445 : :
446 : 21333 : SwClient* SwClientIter::operator++(int)
447 : : {
448 [ + + ]: 21333 : if( pDelNext == pAct )
449 : : {
450 : 21315 : pAct = pAct->pRight;
451 : 21315 : pDelNext = pAct;
452 : : }
453 : : else
454 : 18 : pAct = pDelNext;
455 : 21333 : return pAct;
456 : : }
457 : :
458 : 808555 : SwClient* SwClientIter::GoStart()
459 : : {
460 : 808555 : pAct = const_cast<SwClient*>(rRoot.GetDepends());
461 [ + + ]: 808555 : if( pAct )
462 : : {
463 [ - + ]: 777045 : while( pAct->pLeft )
464 : 0 : pAct = pAct->pLeft;
465 : : }
466 : 808555 : pDelNext = pAct;
467 : 808555 : return pAct;
468 : : }
469 : :
470 : 216 : SwClient* SwClientIter::GoEnd()
471 : : {
472 : 216 : pAct = pDelNext;
473 [ + - ]: 216 : if( !pAct )
474 : 216 : pAct = const_cast<SwClient*>(rRoot.GetDepends());
475 [ - + ]: 216 : if( pAct )
476 : : {
477 [ # # ]: 0 : while( pAct->pRight )
478 : 0 : pAct = pAct->pRight;
479 : : }
480 : 216 : pDelNext = pAct;
481 : 216 : return pAct;
482 : : }
483 : :
484 : 764153 : SwClient* SwClientIter::First( TypeId nType )
485 : : {
486 : 764153 : aSrchId = nType;
487 : 764153 : GoStart();
488 [ + + ]: 764153 : if( pAct )
489 [ + + ]: 792101 : do {
490 [ + + ]: 792101 : if( pAct->IsA( aSrchId ) )
491 : 726642 : break;
492 : :
493 [ + - ]: 65459 : if( pDelNext == pAct )
494 : : {
495 : 65459 : pAct = pAct->pRight;
496 : 65459 : pDelNext = pAct;
497 : : }
498 : : else
499 : 0 : pAct = pDelNext;
500 : : } while( pAct );
501 : 764153 : return pAct;
502 : : }
503 : :
504 : 216 : SwClient* SwClientIter::Last( TypeId nType )
505 : : {
506 : 216 : aSrchId = nType;
507 : 216 : GoEnd();
508 [ - + ]: 216 : if( pAct )
509 [ # # ]: 0 : do {
510 [ # # ]: 0 : if( pAct->IsA( aSrchId ) )
511 : 0 : break;
512 : :
513 [ # # ]: 0 : if( pDelNext == pAct )
514 : 0 : pAct = pAct->pLeft;
515 : : else
516 : 0 : pAct = pDelNext->pLeft;
517 : 0 : pDelNext = pAct;
518 : : } while( pAct );
519 : 216 : return pAct;
520 : : }
521 : :
522 : 879655 : SwClient* SwClientIter::Next()
523 : : {
524 [ + + ]: 638854 : do {
525 [ + + ]: 879655 : if( pDelNext == pAct )
526 : : {
527 : 826560 : pAct = pAct->pRight;
528 : 826560 : pDelNext = pAct;
529 : : }
530 : : else
531 : 53095 : pAct = pDelNext;
532 : :
533 [ + + ][ + + ]: 879655 : if( pAct && pAct->IsA( aSrchId ) )
[ + + ]
534 : 240801 : break;
535 : : } while( pAct );
536 : 589502 : return pAct;
537 : : }
538 : :
539 : 0 : SwClient* SwClientIter::Previous()
540 : : {
541 [ # # ]: 0 : do {
542 [ # # ]: 0 : if( pDelNext == pAct )
543 : 0 : pAct = pAct->pLeft;
544 : : else
545 : 0 : pAct = pDelNext->pLeft;
546 : 0 : pDelNext = pAct;
547 : :
548 [ # # ][ # # ]: 0 : if( pAct && pAct->IsA( aSrchId ) )
[ # # ]
549 : 0 : break;
550 : : } while( pAct );
551 : 0 : return pAct;
552 : : }
553 : :
554 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|