File: | home/maarten/src/libreoffice/core/sw/source/core/docnode/swbaslnk.cxx |
Warning: | line 269, column 9 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <hintids.hxx> | |||
21 | #include <vcl/svapp.hxx> | |||
22 | ||||
23 | #include <sfx2/docfile.hxx> | |||
24 | #include <sfx2/lnkbase.hxx> | |||
25 | #include <sfx2/objsh.hxx> | |||
26 | #include <editeng/boxitem.hxx> | |||
27 | #include <sfx2/linkmgr.hxx> | |||
28 | #include <sfx2/event.hxx> | |||
29 | #include <sot/exchange.hxx> | |||
30 | #include <fmtfsize.hxx> | |||
31 | #include <fmtanchr.hxx> | |||
32 | #include <frmatr.hxx> | |||
33 | #include <frmfmt.hxx> | |||
34 | #include <doc.hxx> | |||
35 | #include <DocumentLinksAdministrationManager.hxx> | |||
36 | #include <IDocumentLayoutAccess.hxx> | |||
37 | #include <pam.hxx> | |||
38 | #include <swtable.hxx> | |||
39 | #include <swevent.hxx> | |||
40 | #include <swbaslnk.hxx> | |||
41 | #include <swserv.hxx> | |||
42 | #include <viewsh.hxx> | |||
43 | #include <ndgrf.hxx> | |||
44 | #include <hints.hxx> | |||
45 | #include <cntfrm.hxx> | |||
46 | #include <htmltbl.hxx> | |||
47 | #include <calbck.hxx> | |||
48 | #include <dialoghelp.hxx> | |||
49 | #include <memory> | |||
50 | ||||
51 | using namespace com::sun::star; | |||
52 | ||||
53 | static bool SetGrfFlySize( const Size& rGrfSz, SwGrfNode* pGrfNd, const Size &rOrigGrfSize ); | |||
54 | ||||
55 | ||||
56 | static void lcl_CallModify( SwGrfNode& rGrfNd, SfxPoolItem& rItem ) | |||
57 | { | |||
58 | //call first all not SwNoTextFrames, then the SwNoTextFrames. | |||
59 | // The reason is, that in the SwNoTextFrames the Graphic | |||
60 | // after a Paint will be swapped out! So all other "behind" | |||
61 | // them haven't a loaded Graphic. | |||
62 | rGrfNd.LockModify(); | |||
63 | { | |||
64 | SwIterator<SwClient,SwGrfNode> aIter(rGrfNd); | |||
65 | for(SwClient* pLast = aIter.First(); pLast; pLast = aIter.Next()) | |||
66 | if(dynamic_cast<const SwContentFrame*>( pLast) == nullptr) | |||
67 | pLast->ModifyNotification(&rItem, &rItem); | |||
68 | } | |||
69 | { | |||
70 | SwIterator<SwContentFrame,SwGrfNode> aIter(rGrfNd); | |||
71 | for(SwClient* pLast = aIter.First(); pLast; pLast = aIter.Next()) | |||
72 | pLast->ModifyNotification(&rItem, &rItem); | |||
73 | } | |||
74 | rGrfNd.UnlockModify(); | |||
75 | } | |||
76 | ||||
77 | ::sfx2::SvBaseLink::UpdateResult SwBaseLink::DataChanged( | |||
78 | const OUString& rMimeType, const uno::Any & rValue ) | |||
79 | { | |||
80 | if( !m_pContentNode ) | |||
81 | { | |||
82 | OSL_ENSURE(false, "DataChanged without ContentNode" )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/swbaslnk.cxx" ":" "82" ": "), "%s", "DataChanged without ContentNode"); } } while (false); | |||
83 | return ERROR_GENERAL; | |||
84 | } | |||
85 | ||||
86 | SwDoc& rDoc = m_pContentNode->GetDoc(); | |||
87 | if( rDoc.IsInDtor() || ChkNoDataFlag() ) | |||
88 | { | |||
89 | return SUCCESS; | |||
90 | } | |||
91 | ||||
92 | SotClipboardFormatId nFormat = SotExchange::GetFormatIdFromMimeType( rMimeType ); | |||
93 | ||||
94 | if( m_pContentNode->IsNoTextNode() && | |||
95 | nFormat == sfx2::LinkManager::RegisterStatusInfoId() ) | |||
96 | { | |||
97 | // Only a status change - serve Events? | |||
98 | OUString sState; | |||
99 | ||||
100 | if( rValue.hasValue() && ( rValue >>= sState )) | |||
101 | { | |||
102 | SvMacroItemId nEvent = SvMacroItemId::NONE; | |||
103 | switch( sState.toInt32() ) | |||
104 | { | |||
105 | case sfx2::LinkManager::STATE_LOAD_OK: nEvent = SvMacroItemId::OnImageLoadDone; break; | |||
106 | case sfx2::LinkManager::STATE_LOAD_ERROR: nEvent = SvMacroItemId::OnImageLoadError; break; | |||
107 | case sfx2::LinkManager::STATE_LOAD_ABORT: nEvent = SvMacroItemId::OnImageLoadCancel; break; | |||
108 | } | |||
109 | ||||
110 | SwFrameFormat* pFormat; | |||
111 | if( nEvent != SvMacroItemId::NONE && nullptr != ( pFormat = m_pContentNode->GetFlyFormat() )) | |||
112 | { | |||
113 | SwCallMouseEvent aCallEvent; | |||
114 | aCallEvent.Set( EVENT_OBJECT_IMAGE, pFormat ); | |||
115 | rDoc.CallEvent( nEvent, aCallEvent ); | |||
116 | } | |||
117 | } | |||
118 | return SUCCESS; // That's it! | |||
119 | } | |||
120 | ||||
121 | bool bUpdate = false; | |||
122 | bool bFrameInPaint = false; | |||
123 | Size aGrfSz, aOldSz; | |||
124 | ||||
125 | SwGrfNode* pSwGrfNode = nullptr; | |||
126 | ||||
127 | if (m_pContentNode->IsGrfNode()) | |||
128 | { | |||
129 | pSwGrfNode = m_pContentNode->GetGrfNode(); | |||
130 | assert(pSwGrfNode && "Error, pSwGrfNode expected when node answers IsGrfNode() with true (!)")(static_cast <bool> (pSwGrfNode && "Error, pSwGrfNode expected when node answers IsGrfNode() with true (!)" ) ? void (0) : __assert_fail ("pSwGrfNode && \"Error, pSwGrfNode expected when node answers IsGrfNode() with true (!)\"" , "/home/maarten/src/libreoffice/core/sw/source/core/docnode/swbaslnk.cxx" , 130, __extension__ __PRETTY_FUNCTION__)); | |||
131 | aOldSz = pSwGrfNode->GetTwipSize(); | |||
132 | const GraphicObject& rGrfObj = pSwGrfNode->GetGrfObj(); | |||
133 | ||||
134 | bFrameInPaint = pSwGrfNode->IsFrameInPaint(); | |||
135 | ||||
136 | Graphic aGrf; | |||
137 | ||||
138 | // tdf#124698 if any auth dialog is needed, find what the parent window should be | |||
139 | weld::Window* pDlgParent = GetFrameWeld(&rDoc); | |||
140 | ||||
141 | if (rDoc.getIDocumentLinksAdministration().GetLinkManager().GetGraphicFromAny(rMimeType, rValue, aGrf, pDlgParent) && | |||
142 | ( GraphicType::Default != aGrf.GetType() || | |||
143 | GraphicType::Default != rGrfObj.GetType() ) ) | |||
144 | { | |||
145 | aGrfSz = ::GetGraphicSizeTwip( aGrf, nullptr ); | |||
146 | ||||
147 | pSwGrfNode->SetGraphic(aGrf); | |||
148 | bUpdate = true; | |||
149 | ||||
150 | // Always use the correct graphic size | |||
151 | if( aGrfSz.Height() && aGrfSz.Width() && | |||
152 | aOldSz.Height() && aOldSz.Width() && | |||
153 | aGrfSz != aOldSz ) | |||
154 | { | |||
155 | pSwGrfNode->SetTwipSize(aGrfSz); | |||
156 | aOldSz = aGrfSz; | |||
157 | } | |||
158 | } | |||
159 | } | |||
160 | else if( m_pContentNode->IsOLENode() ) | |||
161 | bUpdate = true; | |||
162 | ||||
163 | if ( !bUpdate || bFrameInPaint ) | |||
164 | return SUCCESS; | |||
165 | ||||
166 | if (pSwGrfNode) | |||
167 | { | |||
168 | if (!SetGrfFlySize(aGrfSz, pSwGrfNode, aOldSz)) | |||
169 | { | |||
170 | SwMsgPoolItem aMsgHint(RES_GRAPHIC_ARRIVED); | |||
171 | lcl_CallModify(*pSwGrfNode, aMsgHint); | |||
172 | return SUCCESS; | |||
173 | } | |||
174 | } | |||
175 | ||||
176 | return SUCCESS; | |||
177 | } | |||
178 | ||||
179 | static bool SetGrfFlySize( const Size& rGrfSz, SwGrfNode* pGrfNd, const Size& rOrigGrfSize ) | |||
180 | { | |||
181 | bool bRet = false; | |||
182 | SwViewShell *pSh = pGrfNd->GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell(); | |||
183 | std::unique_ptr<CurrShell> pCurr; | |||
184 | if ( pGrfNd->GetDoc().GetEditShell() ) | |||
185 | pCurr.reset(new CurrShell( pSh )); | |||
186 | ||||
187 | Size aSz = rOrigGrfSize; | |||
188 | if ( !(aSz.Width() && aSz.Height()) && | |||
189 | rGrfSz.Width() && rGrfSz.Height() ) | |||
190 | { | |||
191 | SwFrameFormat* pFormat = nullptr; | |||
192 | if (pGrfNd->IsChgTwipSize()) | |||
193 | pFormat = pGrfNd->GetFlyFormat(); | |||
194 | if (nullptr != pFormat) | |||
195 | { | |||
196 | Size aCalcSz( aSz ); | |||
197 | if ( !aSz.Height() && aSz.Width() ) | |||
198 | // Calculate the right height | |||
199 | aCalcSz.setHeight( rGrfSz.Height() * | |||
200 | aSz.Width() / rGrfSz.Width() ); | |||
201 | else if ( !aSz.Width() && aSz.Height() ) | |||
202 | // Calculate the right width | |||
203 | aCalcSz.setWidth( rGrfSz.Width() * | |||
204 | aSz.Height() / rGrfSz.Height() ); | |||
205 | else | |||
206 | // Take over height and width | |||
207 | aCalcSz = rGrfSz; | |||
208 | ||||
209 | const SvxBoxItem &rBox = pFormat->GetBox(); | |||
210 | aCalcSz.AdjustWidth(rBox.CalcLineSpace(SvxBoxItemLine::LEFT) + | |||
211 | rBox.CalcLineSpace(SvxBoxItemLine::RIGHT) ); | |||
212 | aCalcSz.AdjustHeight(rBox.CalcLineSpace(SvxBoxItemLine::TOP) + | |||
213 | rBox.CalcLineSpace(SvxBoxItemLine::BOTTOM) ); | |||
214 | const SwFormatFrameSize& rOldAttr = pFormat->GetFrameSize(); | |||
215 | if( rOldAttr.GetSize() != aCalcSz ) | |||
216 | { | |||
217 | SwFormatFrameSize aAttr( rOldAttr ); | |||
218 | aAttr.SetSize( aCalcSz ); | |||
219 | pFormat->SetFormatAttr( aAttr ); | |||
220 | bRet = true; | |||
221 | } | |||
222 | ||||
223 | if( !aSz.Width() ) | |||
224 | { | |||
225 | // If the graphic is anchored in a table, we need to recalculate | |||
226 | // the table rows | |||
227 | const SwDoc& rDoc = pGrfNd->GetDoc(); | |||
228 | const SwPosition* pAPos = pFormat->GetAnchor().GetContentAnchor(); | |||
229 | SwTableNode *pTableNd; | |||
230 | if (pAPos && nullptr != (pTableNd = pAPos->nNode.GetNode().FindTableNode())) | |||
231 | { | |||
232 | const bool bLastGrf = !pTableNd->GetTable().DecGrfsThatResize(); | |||
233 | SwHTMLTableLayout *pLayout = | |||
234 | pTableNd->GetTable().GetHTMLTableLayout(); | |||
235 | if( pLayout ) | |||
236 | { | |||
237 | const sal_uInt16 nBrowseWidth = | |||
238 | pLayout->GetBrowseWidthByTable( rDoc ); | |||
239 | if ( nBrowseWidth ) | |||
240 | { | |||
241 | pLayout->Resize( nBrowseWidth, true, true, | |||
242 | bLastGrf ? HTMLTABLE_RESIZE_NOW((9223372036854775807L *2UL+1UL)) | |||
243 | : 500 ); | |||
244 | } | |||
245 | } | |||
246 | } | |||
247 | } | |||
248 | } | |||
249 | ||||
250 | // SetTwipSize rescales an ImageMap if needed for which | |||
251 | // it requires the Frame Format | |||
252 | pGrfNd->SetTwipSize( rGrfSz ); | |||
253 | } | |||
254 | ||||
255 | return bRet; | |||
256 | } | |||
257 | ||||
258 | bool SwBaseLink::SwapIn( bool bWaitForData, bool bNativFormat ) | |||
259 | { | |||
260 | if( !GetObj() && ( bNativFormat || ( !IsSynchron() && bWaitForData ) )) | |||
| ||||
261 | { | |||
262 | AddNextRef(); | |||
263 | GetRealObject_(); | |||
264 | ReleaseRef(); | |||
265 | } | |||
266 | ||||
267 | bool bRes = false; | |||
268 | ||||
269 | if( GetObj() ) | |||
| ||||
270 | { | |||
271 | OUString aMimeType( SotExchange::GetFormatMimeType( GetContentType() )); | |||
272 | uno::Any aValue; | |||
273 | (void)GetObj()->GetData( aValue, aMimeType, !IsSynchron() && bWaitForData ); | |||
274 | ||||
275 | if( bWaitForData && !GetObj() ) | |||
276 | { | |||
277 | OSL_ENSURE( false, "The SvxFileObject was deleted in a GetData!" )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/swbaslnk.cxx" ":" "277" ": "), "%s", "The SvxFileObject was deleted in a GetData!" ); } } while (false); | |||
278 | } | |||
279 | else | |||
280 | { | |||
281 | bRes = aValue.hasValue(); | |||
282 | if ( bRes ) | |||
283 | { | |||
284 | DataChanged( aMimeType, aValue ); | |||
285 | } | |||
286 | } | |||
287 | } | |||
288 | else if( !IsSynchron() && bWaitForData ) | |||
289 | { | |||
290 | SetSynchron( true ); | |||
291 | bRes = Update(); | |||
292 | SetSynchron( false ); | |||
293 | } | |||
294 | else | |||
295 | bRes = Update(); | |||
296 | ||||
297 | return bRes; | |||
298 | } | |||
299 | ||||
300 | void SwBaseLink::Closed() | |||
301 | { | |||
302 | if( m_pContentNode && !m_pContentNode->GetDoc().IsInDtor() ) | |||
303 | { | |||
304 | // Delete the connection | |||
305 | if( m_pContentNode->IsGrfNode() ) | |||
306 | static_cast<SwGrfNode*>(m_pContentNode)->ReleaseLink(); | |||
307 | } | |||
308 | SvBaseLink::Closed(); | |||
309 | } | |||
310 | ||||
311 | const SwNode* SwBaseLink::GetAnchor() const | |||
312 | { | |||
313 | if (m_pContentNode) | |||
314 | { | |||
315 | SwFrameFormat *const pFormat = m_pContentNode->GetFlyFormat(); | |||
316 | if (pFormat) | |||
317 | { | |||
318 | const SwFormatAnchor& rAnchor = pFormat->GetAnchor(); | |||
319 | SwPosition const*const pAPos = rAnchor.GetContentAnchor(); | |||
320 | if (pAPos && | |||
321 | ((RndStdIds::FLY_AS_CHAR == rAnchor.GetAnchorId()) || | |||
322 | (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId()) || | |||
323 | (RndStdIds::FLY_AT_FLY == rAnchor.GetAnchorId()) || | |||
324 | (RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId()))) | |||
325 | { | |||
326 | return &pAPos->nNode.GetNode(); | |||
327 | } | |||
328 | return nullptr; | |||
329 | } | |||
330 | } | |||
331 | ||||
332 | OSL_ENSURE( false, "GetAnchor is not shadowed" )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/swbaslnk.cxx" ":" "332" ": "), "%s", "GetAnchor is not shadowed"); } } while (false); | |||
333 | return nullptr; | |||
334 | } | |||
335 | ||||
336 | bool SwBaseLink::IsRecursion( const SwBaseLink* pChkLnk ) const | |||
337 | { | |||
338 | tools::SvRef<SwServerObject> aRef( static_cast<SwServerObject*>(GetObj()) ); | |||
339 | if( aRef.is() ) | |||
340 | { | |||
341 | // As it's a ServerObject, we query all contained Links | |||
342 | // if we are contained in them. Else we have a recursion. | |||
343 | return aRef->IsLinkInServer( pChkLnk ); | |||
344 | } | |||
345 | return false; | |||
346 | } | |||
347 | ||||
348 | bool SwBaseLink::IsInRange( sal_uLong, sal_uLong ) const | |||
349 | { | |||
350 | // Not Graphic or OLE Links | |||
351 | // Fields or Sections have their own derivation! | |||
352 | return false; | |||
353 | } | |||
354 | ||||
355 | SwBaseLink::~SwBaseLink() | |||
356 | { | |||
357 | } | |||
358 | ||||
359 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | #ifndef INCLUDED_TOOLS_REF_HXX |
20 | #define INCLUDED_TOOLS_REF_HXX |
21 | |
22 | #include <sal/config.h> |
23 | #include <cassert> |
24 | #include <tools/toolsdllapi.h> |
25 | #include <utility> |
26 | |
27 | /** |
28 | This implements similar functionality to boost::intrusive_ptr |
29 | */ |
30 | |
31 | namespace tools { |
32 | |
33 | /** T must be a class that extends SvRefBase */ |
34 | template<typename T> class SAL_DLLPUBLIC_RTTI__attribute__ ((type_visibility("default"))) SvRef final { |
35 | public: |
36 | SvRef(): pObj(nullptr) {} |
37 | |
38 | SvRef(SvRef&& rObj) noexcept |
39 | { |
40 | pObj = rObj.pObj; |
41 | rObj.pObj = nullptr; |
42 | } |
43 | |
44 | SvRef(SvRef const & rObj): pObj(rObj.pObj) |
45 | { |
46 | if (pObj != nullptr) pObj->AddNextRef(); |
47 | } |
48 | |
49 | SvRef(T * pObjP): pObj(pObjP) |
50 | { |
51 | if (pObj != nullptr) pObj->AddFirstRef(); |
52 | } |
53 | |
54 | ~SvRef() |
55 | { |
56 | if (pObj != nullptr) pObj->ReleaseRef(); |
57 | } |
58 | |
59 | void clear() |
60 | { |
61 | if (pObj != nullptr) { |
62 | T * pRefObj = pObj; |
63 | pObj = nullptr; |
64 | pRefObj->ReleaseRef(); |
65 | } |
66 | } |
67 | |
68 | SvRef & operator =(SvRef const & rObj) |
69 | { |
70 | if (rObj.pObj != nullptr) { |
71 | rObj.pObj->AddNextRef(); |
72 | } |
73 | T * pRefObj = pObj; |
74 | pObj = rObj.pObj; |
75 | if (pRefObj != nullptr) { |
76 | pRefObj->ReleaseRef(); |
77 | } |
78 | return *this; |
79 | } |
80 | |
81 | SvRef & operator =(SvRef && rObj) |
82 | { |
83 | if (pObj != nullptr) { |
84 | pObj->ReleaseRef(); |
85 | } |
86 | pObj = rObj.pObj; |
87 | rObj.pObj = nullptr; |
88 | return *this; |
89 | } |
90 | |
91 | bool is() const { return pObj != nullptr; } |
92 | |
93 | explicit operator bool() const { return is(); } |
94 | |
95 | T * get() const { return pObj; } |
96 | |
97 | T * operator ->() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 97, __extension__ __PRETTY_FUNCTION__)); return pObj; } |
98 | |
99 | T & operator *() const { assert(pObj != nullptr)(static_cast <bool> (pObj != nullptr) ? void (0) : __assert_fail ("pObj != nullptr", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 99, __extension__ __PRETTY_FUNCTION__)); return *pObj; } |
100 | |
101 | bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } |
102 | bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } |
103 | |
104 | private: |
105 | T * pObj; |
106 | }; |
107 | |
108 | /** |
109 | * This implements similar functionality to std::make_shared. |
110 | */ |
111 | template<typename T, typename... Args> |
112 | SvRef<T> make_ref(Args&& ... args) |
113 | { |
114 | return SvRef<T>(new T(std::forward<Args>(args)...)); |
115 | } |
116 | |
117 | } |
118 | |
119 | /** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ |
120 | class TOOLS_DLLPUBLIC__attribute__ ((visibility("default"))) SvRefBase |
121 | { |
122 | // work around a clang 3.5 optimization bug: if the bNoDelete is *first* |
123 | // it mis-compiles "if (--nRefCount == 0)" and never deletes any object |
124 | unsigned int nRefCount : 31; |
125 | // the only reason this is not bool is because MSVC cannot handle mixed type bitfields |
126 | unsigned int bNoDelete : 1; |
127 | |
128 | protected: |
129 | virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; |
130 | |
131 | public: |
132 | SvRefBase() : nRefCount(0), bNoDelete(1) {} |
133 | SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} |
134 | |
135 | SvRefBase & operator=(const SvRefBase &) { return *this; } |
136 | |
137 | void RestoreNoDelete() |
138 | { bNoDelete = 1; } |
139 | |
140 | void AddNextRef() |
141 | { |
142 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 142, __extension__ __PRETTY_FUNCTION__)); |
143 | ++nRefCount; |
144 | } |
145 | |
146 | void AddFirstRef() |
147 | { |
148 | assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" )(static_cast <bool> (nRefCount < (1 << 30) && "Do not add refs to dead objects") ? void (0) : __assert_fail ("nRefCount < (1 << 30) && \"Do not add refs to dead objects\"" , "/home/maarten/src/libreoffice/core/include/tools/ref.hxx", 148, __extension__ __PRETTY_FUNCTION__)); |
149 | if( bNoDelete ) |
150 | bNoDelete = 0; |
151 | ++nRefCount; |
152 | } |
153 | |
154 | void ReleaseRef() |
155 | { |
156 | assert( nRefCount >= 1)(static_cast <bool> (nRefCount >= 1) ? void (0) : __assert_fail ("nRefCount >= 1", "/home/maarten/src/libreoffice/core/include/tools/ref.hxx" , 156, __extension__ __PRETTY_FUNCTION__)); |
157 | if( --nRefCount == 0 && !bNoDelete) |
158 | { |
159 | // I'm not sure about the original purpose of this line, but right now |
160 | // it serves the purpose that anything that attempts to do an AddRef() |
161 | // after an object is deleted will trip an assert. |
162 | nRefCount = 1 << 30; |
163 | delete this; |
164 | } |
165 | } |
166 | |
167 | unsigned int GetRefCount() const |
168 | { return nRefCount; } |
169 | }; |
170 | |
171 | template<typename T> |
172 | class SvCompatWeakBase; |
173 | |
174 | /** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. |
175 | */ |
176 | template<typename T> |
177 | class SvCompatWeakHdl final : public SvRefBase |
178 | { |
179 | friend class SvCompatWeakBase<T>; |
180 | T* _pObj; |
181 | |
182 | SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} |
183 | |
184 | public: |
185 | void ResetWeakBase( ) { _pObj = nullptr; } |
186 | T* GetObj() { return _pObj; } |
187 | }; |
188 | |
189 | /** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. |
190 | Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. |
191 | */ |
192 | template<typename T> |
193 | class SvCompatWeakBase |
194 | { |
195 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
196 | |
197 | public: |
198 | /** Does not use initializer due to compiler warnings, |
199 | because the lifetime of the _xHdl object can exceed the lifetime of this class. |
200 | */ |
201 | SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } |
202 | |
203 | ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } |
204 | |
205 | SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } |
206 | }; |
207 | |
208 | /** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. |
209 | */ |
210 | template<typename T> |
211 | class SAL_WARN_UNUSED__attribute__((warn_unused)) SvCompatWeakRef |
212 | { |
213 | tools::SvRef< SvCompatWeakHdl<T> > _xHdl; |
214 | public: |
215 | SvCompatWeakRef( ) {} |
216 | SvCompatWeakRef( T* pObj ) |
217 | { if( pObj ) _xHdl = pObj->GetHdl(); } |
218 | #if defined(__COVERITY__) |
219 | ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} |
220 | #endif |
221 | SvCompatWeakRef& operator = ( T * pObj ) |
222 | { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } |
223 | bool is() const |
224 | { return _xHdl.is() && _xHdl->GetObj(); } |
225 | explicit operator bool() const { return is(); } |
226 | T* operator -> () const |
227 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
228 | operator T* () const |
229 | { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } |
230 | }; |
231 | |
232 | #endif |
233 | |
234 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |