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 660090 : sw::LegacyModifyHint::~LegacyModifyHint() {}
27 :
28 2078486 : TYPEINIT0( SwClient );
29 :
30 18341972 : SwClient::~SwClient()
31 : {
32 : OSL_ENSURE( !pRegisteredIn || pRegisteredIn->HasWriterListeners(), "SwModify still known, but Client already disconnected!" );
33 9170986 : if( pRegisteredIn && pRegisteredIn->HasWriterListeners() )
34 979952 : pRegisteredIn->Remove( this );
35 9170986 : }
36 :
37 132897 : void SwClient::CheckRegistration( const SfxPoolItem* pOld, const SfxPoolItem* )
38 : {
39 : // this method only handles notification about dying SwModify objects
40 132897 : if( (!pOld || pOld->Which() != RES_OBJECTDYING) )
41 126730 : return;
42 :
43 6167 : const SwPtrMsgPoolItem* pDead = static_cast<const SwPtrMsgPoolItem*>(pOld);
44 6167 : if(pDead && pDead->pObject == pRegisteredIn)
45 : {
46 : // I've got a notification from the object I know
47 6130 : SwModify* pAbove = pRegisteredIn->GetRegisteredIn();
48 6130 : if(pAbove)
49 : {
50 : // if the dying object itself was listening at an SwModify, I take over
51 : // adding myself to pAbove will automatically remove me from my current pRegisteredIn
52 41 : pAbove->Add(this);
53 41 : return;
54 : }
55 : // destroy connection
56 6089 : pRegisteredIn->Remove(this);
57 : }
58 : }
59 :
60 1291592 : void SwClient::SwClientNotify(const SwModify&, const SfxHint& rHint)
61 : {
62 1291592 : if (typeid(rHint) == typeid(sw::LegacyModifyHint))
63 : {
64 1238605 : auto pLegacyHint(static_cast<const sw::LegacyModifyHint*>(&rHint));
65 1238605 : Modify(pLegacyHint->m_pOld, pLegacyHint->m_pNew);
66 : }
67 1291592 : };
68 :
69 108824 : void SwClient::Modify(SfxPoolItem const*const pOldValue, SfxPoolItem const*const pNewValue)
70 : {
71 108824 : CheckRegistration( pOldValue, pNewValue );
72 108824 : }
73 :
74 2119486 : SwModify::~SwModify()
75 : {
76 : OSL_ENSURE( !IsModifyLocked(), "Modify destroyed but locked." );
77 :
78 1059743 : if ( IsInCache() )
79 15518 : SwFrm::GetCache().Delete( this );
80 :
81 1059743 : if ( IsInSwFntCache() )
82 0 : pSwFontCache->Delete( this );
83 :
84 1059743 : if( m_pWriterListeners )
85 : {
86 : // there are depending objects
87 113696 : if( IsInDocDTOR() )
88 : {
89 : // If the document gets destroyed anyway, just tell clients to
90 : // forget me so that they don't try to get removed from my list
91 : // later when they also get destroyed
92 133 : SwIterator<SwClient,SwModify> aIter(*this);
93 477 : for(SwClient* pClient = aIter.First(); pClient; pClient = aIter.Next())
94 477 : pClient->pRegisteredIn = nullptr;
95 : }
96 : else
97 : {
98 : // notify all clients that they shall remove themselves
99 113563 : SwPtrMsgPoolItem aDyObject( RES_OBJECTDYING, this );
100 113563 : NotifyClients( &aDyObject, &aDyObject );
101 :
102 : // remove all clients that have not done themselves
103 : // mba: possibly a hotfix for forgotten base class calls?!
104 233198 : while( m_pWriterListeners )
105 119635 : static_cast<SwClient*>(m_pWriterListeners)->CheckRegistration( &aDyObject, &aDyObject );
106 : }
107 : }
108 1059743 : }
109 :
110 2723583 : void SwModify::NotifyClients( const SfxPoolItem* pOldValue, const SfxPoolItem* pNewValue )
111 : {
112 2723583 : if ( IsInCache() || IsInSwFntCache() )
113 : {
114 : const sal_uInt16 nWhich = pOldValue ? pOldValue->Which() :
115 31303 : pNewValue ? pNewValue->Which() : 0;
116 31303 : CheckCaching( nWhich );
117 : }
118 :
119 2723583 : if ( !m_pWriterListeners || IsModifyLocked() )
120 4787922 : return;
121 :
122 659244 : LockModify();
123 :
124 : // mba: WTF?!
125 659244 : if( !pOldValue )
126 : {
127 79108 : bLockClientList = true;
128 : }
129 : else
130 : {
131 580136 : switch( pOldValue->Which() )
132 : {
133 : case RES_OBJECTDYING:
134 : case RES_REMOVE_UNO_OBJECT:
135 114915 : bLockClientList = static_cast<const SwPtrMsgPoolItem*>(pOldValue)->pObject != this;
136 114915 : break;
137 :
138 : default:
139 465221 : bLockClientList = true;
140 : }
141 : }
142 :
143 659244 : ModifyBroadcast( pOldValue, pNewValue );
144 659244 : bLockClientList = false;
145 659244 : UnlockModify();
146 : }
147 :
148 1278958 : bool SwModify::GetInfo( SfxPoolItem& rInfo ) const
149 : {
150 1278958 : if(!m_pWriterListeners)
151 915819 : return true;
152 363139 : SwIterator<SwClient,SwModify> aIter(*this);
153 1117100 : for(SwClient* pClient = aIter.First(); pClient; pClient = aIter.Next())
154 936625 : if(!pClient->GetInfo( rInfo ))
155 182664 : return false;
156 180475 : return true;
157 : }
158 :
159 1703283 : void SwModify::Add( SwClient* pDepend )
160 : {
161 : OSL_ENSURE( !bLockClientList, "Client inserted while in Modify" );
162 :
163 1703283 : if(pDepend->pRegisteredIn != this )
164 : {
165 : #if OSL_DEBUG_LEVEL > 0
166 : if(sw::ClientIteratorBase::our_pClientIters)
167 : {
168 : for(auto& rIter : sw::ClientIteratorBase::our_pClientIters->GetRingContainer())
169 : {
170 : SAL_WARN_IF(&rIter.m_rRoot == m_pWriterListeners, "sw.core", "a " << typeid(*pDepend).name() << " client added as listener to a " << typeid(*this).name() << " during client iteration.");
171 : }
172 : }
173 : #endif
174 : // deregister new client in case it is already registered elsewhere
175 1585837 : if( pDepend->pRegisteredIn != nullptr )
176 92952 : pDepend->pRegisteredIn->Remove( pDepend );
177 :
178 1585837 : if( !m_pWriterListeners )
179 : {
180 : // first client added
181 650280 : m_pWriterListeners = pDepend;
182 650280 : m_pWriterListeners->m_pLeft = nullptr;
183 650280 : m_pWriterListeners->m_pRight = nullptr;
184 : }
185 : else
186 : {
187 : // append client
188 935557 : pDepend->m_pRight = m_pWriterListeners->m_pRight;
189 935557 : m_pWriterListeners->m_pRight = pDepend;
190 935557 : pDepend->m_pLeft = m_pWriterListeners;
191 935557 : if( pDepend->m_pRight )
192 753584 : pDepend->m_pRight->m_pLeft = pDepend;
193 : }
194 :
195 : // connect client to me
196 1585837 : pDepend->pRegisteredIn = this;
197 : }
198 1703283 : }
199 :
200 1583015 : SwClient* SwModify::Remove( SwClient* pDepend )
201 : {
202 1583015 : if(m_bInDocDTOR)
203 0 : return nullptr;
204 :
205 : assert(pDepend->pRegisteredIn == this);
206 :
207 : // SwClient is my listener
208 : // remove it from my list
209 1583015 : ::sw::WriterListener* pR = pDepend->m_pRight;
210 1583015 : ::sw::WriterListener* pL = pDepend->m_pLeft;
211 1583015 : if( m_pWriterListeners == pDepend )
212 804071 : m_pWriterListeners = pL ? pL : pR;
213 :
214 1583015 : if( pL )
215 778944 : pL->m_pRight = pR;
216 1583015 : if( pR )
217 792430 : pR->m_pLeft = pL;
218 :
219 : // update ClientIterators
220 1583015 : if(sw::ClientIteratorBase::our_pClientIters)
221 : {
222 595908 : for(auto& rIter : sw::ClientIteratorBase::our_pClientIters->GetRingContainer())
223 : {
224 304365 : if( rIter.m_pCurrent == pDepend || rIter.m_pPosition == pDepend )
225 : {
226 : // if object being removed is the current or next object in an
227 : // iterator, advance this iterator
228 274156 : rIter.m_pPosition = static_cast<SwClient*>(pR);
229 : }
230 : }
231 : }
232 1583015 : pDepend->m_pLeft = nullptr;
233 1583015 : pDepend->m_pRight = nullptr;
234 1583015 : pDepend->pRegisteredIn = nullptr;
235 1583015 : return pDepend;
236 : }
237 :
238 33821 : void SwModify::CheckCaching( const sal_uInt16 nWhich )
239 : {
240 33821 : if( isCHRATR( nWhich ) )
241 : {
242 0 : SetInSwFntCache( false );
243 : }
244 : else
245 : {
246 33821 : switch( nWhich )
247 : {
248 : case RES_OBJECTDYING:
249 : case RES_FMT_CHG:
250 : case RES_ATTRSET_CHG:
251 23663 : SetInSwFntCache( false );
252 : // fall through
253 : case RES_UL_SPACE:
254 : case RES_LR_SPACE:
255 : case RES_BOX:
256 : case RES_SHADOW:
257 : case RES_FRM_SIZE:
258 : case RES_KEEP:
259 : case RES_BREAK:
260 24256 : if( IsInCache() )
261 : {
262 19639 : SwFrm::GetCache().Delete( this );
263 19639 : SetInCache( false );
264 : }
265 24256 : break;
266 : }
267 : }
268 33821 : }
269 :
270 177 : sw::ClientIteratorBase* sw::ClientIteratorBase::our_pClientIters = nullptr;
271 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|