File: | home/maarten/src/libreoffice/core/include/tools/ref.hxx |
Warning: | line 91, column 38 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 | |||||
21 | #include <memory> | ||||
22 | #include <sfx2/lnkbase.hxx> | ||||
23 | #include <sot/exchange.hxx> | ||||
24 | #include <com/sun/star/uno/Any.hxx> | ||||
25 | #include <com/sun/star/uno/Sequence.hxx> | ||||
26 | #include <com/sun/star/ui/dialogs/TemplateDescription.hpp> | ||||
27 | #include <sfx2/linkmgr.hxx> | ||||
28 | #include <vcl/svapp.hxx> | ||||
29 | #include <vcl/weld.hxx> | ||||
30 | #include <sfx2/strings.hrc> | ||||
31 | #include <sfx2/sfxresid.hxx> | ||||
32 | #include <sfx2/filedlghelper.hxx> | ||||
33 | #include <tools/debug.hxx> | ||||
34 | #include <svl/svdde.hxx> | ||||
35 | #include <osl/diagnose.h> | ||||
36 | |||||
37 | using namespace ::com::sun::star; | ||||
38 | using namespace ::com::sun::star::uno; | ||||
39 | |||||
40 | namespace sfx2 | ||||
41 | { | ||||
42 | |||||
43 | namespace { | ||||
44 | |||||
45 | class ImplDdeItem; | ||||
46 | |||||
47 | } | ||||
48 | |||||
49 | struct BaseLink_Impl | ||||
50 | { | ||||
51 | Link<SvBaseLink&,void> m_aEndEditLink; | ||||
52 | LinkManager* m_pLinkMgr; | ||||
53 | weld::Window* m_pParentWin; | ||||
54 | std::unique_ptr<FileDialogHelper> | ||||
55 | m_pFileDlg; | ||||
56 | bool m_bIsConnect; | ||||
57 | |||||
58 | BaseLink_Impl() : | ||||
59 | m_pLinkMgr( nullptr ) | ||||
60 | , m_pParentWin( nullptr ) | ||||
61 | , m_bIsConnect( false ) | ||||
62 | {} | ||||
63 | }; | ||||
64 | |||||
65 | // only for internal management | ||||
66 | struct ImplBaseLinkData | ||||
67 | { | ||||
68 | struct tClientType | ||||
69 | { | ||||
70 | // applies for all links | ||||
71 | SotClipboardFormatId nCntntType; // Update Format | ||||
72 | // Not Ole-Links | ||||
73 | bool bIntrnlLnk; // It is an internal link | ||||
74 | SfxLinkUpdateMode nUpdateMode; // UpdateMode | ||||
75 | }; | ||||
76 | |||||
77 | struct tDDEType | ||||
78 | { | ||||
79 | ImplDdeItem* pItem; | ||||
80 | }; | ||||
81 | |||||
82 | union { | ||||
83 | tClientType ClientType; | ||||
84 | tDDEType DDEType; | ||||
85 | }; | ||||
86 | ImplBaseLinkData() | ||||
87 | { | ||||
88 | ClientType.nCntntType = SotClipboardFormatId::NONE; | ||||
89 | ClientType.bIntrnlLnk = false; | ||||
90 | ClientType.nUpdateMode = SfxLinkUpdateMode::NONE; | ||||
91 | DDEType.pItem = nullptr; | ||||
92 | } | ||||
93 | }; | ||||
94 | |||||
95 | namespace { | ||||
96 | |||||
97 | class ImplDdeItem : public DdeGetPutItem | ||||
98 | { | ||||
99 | SvBaseLink* pLink; | ||||
100 | DdeData aData; | ||||
101 | Sequence< sal_Int8 > aSeq; // Datacontainer for DdeData !!! | ||||
102 | bool bIsValidData : 1; | ||||
103 | bool bIsInDTOR : 1; | ||||
104 | public: | ||||
105 | #if defined(_WIN32) | ||||
106 | ImplDdeItem( SvBaseLink& rLink, const OUString& rStr ) | ||||
107 | : DdeGetPutItem( rStr ), pLink( &rLink ), bIsValidData( false ), | ||||
108 | bIsInDTOR( false ) | ||||
109 | {} | ||||
110 | #endif | ||||
111 | virtual ~ImplDdeItem() override; | ||||
112 | |||||
113 | virtual DdeData* Get( SotClipboardFormatId ) override; | ||||
114 | virtual bool Put( const DdeData* ) override; | ||||
115 | virtual void AdviseLoop( bool ) override; | ||||
116 | |||||
117 | void Notify() | ||||
118 | { | ||||
119 | bIsValidData = false; | ||||
120 | DdeGetPutItem::NotifyClient(); | ||||
121 | } | ||||
122 | |||||
123 | bool IsInDTOR() const { return bIsInDTOR; } | ||||
124 | }; | ||||
125 | |||||
126 | } | ||||
127 | |||||
128 | SvBaseLink::SvBaseLink() | ||||
129 | : pImpl ( new BaseLink_Impl ), | ||||
130 | m_bIsReadOnly(false) | ||||
131 | { | ||||
132 | mnObjType = SvBaseLinkObjectType::ClientSo; | ||||
133 | pImplData.reset( new ImplBaseLinkData ); | ||||
134 | bVisible = bSynchron = true; | ||||
135 | bWasLastEditOK = false; | ||||
136 | } | ||||
137 | |||||
138 | |||||
139 | SvBaseLink::SvBaseLink( SfxLinkUpdateMode nUpdateMode, SotClipboardFormatId nContentType ) | ||||
140 | : pImpl( new BaseLink_Impl ), | ||||
141 | m_bIsReadOnly(false) | ||||
142 | { | ||||
143 | mnObjType = SvBaseLinkObjectType::ClientSo; | ||||
144 | pImplData.reset( new ImplBaseLinkData ); | ||||
145 | bVisible = bSynchron = true; | ||||
146 | bWasLastEditOK = false; | ||||
147 | |||||
148 | // It is going to be an OLE-Link, | ||||
149 | pImplData->ClientType.nUpdateMode = nUpdateMode; | ||||
150 | pImplData->ClientType.nCntntType = nContentType; | ||||
151 | pImplData->ClientType.bIntrnlLnk = false; | ||||
152 | } | ||||
153 | |||||
154 | #if defined(_WIN32) | ||||
155 | |||||
156 | static DdeTopic* FindTopic( const OUString & rLinkName, sal_uInt16* pItemStt ) | ||||
157 | { | ||||
158 | if( rLinkName.isEmpty() ) | ||||
159 | return nullptr; | ||||
160 | |||||
161 | OUString sNm( rLinkName ); | ||||
162 | sal_Int32 nTokenPos = 0; | ||||
163 | OUString sService( sNm.getToken( 0, cTokenSeparator, nTokenPos ) ); | ||||
164 | |||||
165 | DdeServices& rSvc = DdeService::GetServices(); | ||||
166 | for (auto const& elem : rSvc) | ||||
167 | { | ||||
168 | if(elem->GetName() == sService) | ||||
169 | { | ||||
170 | // then we search for the Topic | ||||
171 | OUString sTopic( sNm.getToken( 0, cTokenSeparator, nTokenPos ) ); | ||||
172 | if( pItemStt ) | ||||
173 | *pItemStt = nTokenPos; | ||||
174 | |||||
175 | std::vector<DdeTopic*>& rTopics = elem->GetTopics(); | ||||
176 | |||||
177 | for (auto const& topic : rTopics) | ||||
178 | if( topic->GetName() == sTopic ) | ||||
179 | return topic; | ||||
180 | break; | ||||
181 | } | ||||
182 | } | ||||
183 | return nullptr; | ||||
184 | } | ||||
185 | |||||
186 | SvBaseLink::SvBaseLink( const OUString& rLinkName, SvBaseLinkObjectType nObjectType, SvLinkSource* pObj ) | ||||
187 | : pImpl() | ||||
188 | , m_bIsReadOnly(false) | ||||
189 | { | ||||
190 | bVisible = bSynchron = true; | ||||
191 | bWasLastEditOK = false; | ||||
192 | aLinkName = rLinkName; | ||||
193 | pImplData.reset( new ImplBaseLinkData ); | ||||
194 | mnObjType = nObjectType; | ||||
195 | |||||
196 | if( !pObj ) | ||||
197 | { | ||||
198 | DBG_ASSERT( pObj, "Where is my left-most object" )do { if (true && (!(pObj))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/lnkbase2.cxx" ":" "198" ": "), "%s", "Where is my left-most object"); } } while (false); | ||||
199 | return; | ||||
200 | } | ||||
201 | |||||
202 | if( SvBaseLinkObjectType::DdeExternal == mnObjType ) | ||||
203 | { | ||||
204 | sal_uInt16 nItemStt = 0; | ||||
205 | DdeTopic* pTopic = FindTopic( aLinkName, &nItemStt ); | ||||
206 | if( pTopic ) | ||||
207 | { | ||||
208 | // then we have it all together | ||||
209 | // MM_TODO how do I get the name | ||||
210 | OUString aStr = aLinkName; // xLinkName->GetDisplayName(); | ||||
211 | aStr = aStr.copy( nItemStt ); | ||||
212 | pImplData->DDEType.pItem = new ImplDdeItem( *this, aStr ); | ||||
213 | pTopic->InsertItem( pImplData->DDEType.pItem ); | ||||
214 | |||||
215 | // store the Advice | ||||
216 | xObj = pObj; | ||||
217 | } | ||||
218 | } | ||||
219 | else if( pObj->Connect( this ) ) | ||||
220 | xObj = pObj; | ||||
221 | } | ||||
222 | |||||
223 | #endif | ||||
224 | |||||
225 | SvBaseLink::~SvBaseLink() | ||||
226 | { | ||||
227 | Disconnect(); | ||||
228 | |||||
229 | if( mnObjType == SvBaseLinkObjectType::DdeExternal ) | ||||
230 | { | ||||
231 | if( !pImplData->DDEType.pItem->IsInDTOR() ) | ||||
232 | delete pImplData->DDEType.pItem; | ||||
233 | } | ||||
234 | |||||
235 | pImplData.reset(); | ||||
236 | } | ||||
237 | |||||
238 | IMPL_LINK( SvBaseLink, EndEditHdl, const OUString&, _rNewName, void )void SvBaseLink::LinkStubEndEditHdl(void * instance, const OUString & data) { return static_cast<SvBaseLink *>(instance )->EndEditHdl(data); } void SvBaseLink::EndEditHdl(const OUString & _rNewName) | ||||
239 | { | ||||
240 | OUString sNewName = _rNewName; | ||||
241 | if ( !ExecuteEdit( sNewName ) ) | ||||
242 | sNewName.clear(); | ||||
243 | bWasLastEditOK = !sNewName.isEmpty(); | ||||
244 | pImpl->m_aEndEditLink.Call( *this ); | ||||
245 | } | ||||
246 | |||||
247 | |||||
248 | void SvBaseLink::SetObjType( SvBaseLinkObjectType mnObjTypeP ) | ||||
249 | { | ||||
250 | DBG_ASSERT( mnObjType != SvBaseLinkObjectType::ClientDde, "type already set" )do { if (true && (!(mnObjType != SvBaseLinkObjectType ::ClientDde))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/lnkbase2.cxx" ":" "250" ": "), "%s", "type already set"); } } while (false ); | ||||
251 | DBG_ASSERT( !xObj.is(), "object exist" )do { if (true && (!(!xObj.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/lnkbase2.cxx" ":" "251" ": "), "%s", "object exist"); } } while (false); | ||||
252 | |||||
253 | mnObjType = mnObjTypeP; | ||||
254 | } | ||||
255 | |||||
256 | |||||
257 | void SvBaseLink::SetName( const OUString & rNm ) | ||||
258 | { | ||||
259 | aLinkName = rNm; | ||||
260 | } | ||||
261 | |||||
262 | |||||
263 | void SvBaseLink::SetObj( SvLinkSource * pObj ) | ||||
264 | { | ||||
265 | DBG_ASSERT( (isClientType(mnObjType) &&do { if (true && (!((isClientType(mnObjType) && pImplData->ClientType.bIntrnlLnk) || mnObjType == SvBaseLinkObjectType ::ClientGraphic))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/lnkbase2.cxx" ":" "268" ": "), "%s", "no intern link"); } } while (false) | ||||
266 | pImplData->ClientType.bIntrnlLnk) ||do { if (true && (!((isClientType(mnObjType) && pImplData->ClientType.bIntrnlLnk) || mnObjType == SvBaseLinkObjectType ::ClientGraphic))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/lnkbase2.cxx" ":" "268" ": "), "%s", "no intern link"); } } while (false) | ||||
267 | mnObjType == SvBaseLinkObjectType::ClientGraphic,do { if (true && (!((isClientType(mnObjType) && pImplData->ClientType.bIntrnlLnk) || mnObjType == SvBaseLinkObjectType ::ClientGraphic))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/lnkbase2.cxx" ":" "268" ": "), "%s", "no intern link"); } } while (false) | ||||
268 | "no intern link" )do { if (true && (!((isClientType(mnObjType) && pImplData->ClientType.bIntrnlLnk) || mnObjType == SvBaseLinkObjectType ::ClientGraphic))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/lnkbase2.cxx" ":" "268" ": "), "%s", "no intern link"); } } while (false); | ||||
269 | xObj = pObj; | ||||
270 | } | ||||
271 | |||||
272 | |||||
273 | void SvBaseLink::SetLinkSourceName( const OUString & rLnkNm ) | ||||
274 | { | ||||
275 | if( aLinkName == rLnkNm ) | ||||
276 | return; | ||||
277 | |||||
278 | AddNextRef(); // should be superfluous | ||||
279 | // remove old connection | ||||
280 | Disconnect(); | ||||
281 | |||||
282 | aLinkName = rLnkNm; | ||||
283 | |||||
284 | // New Connection | ||||
285 | GetRealObject_(); | ||||
286 | ReleaseRef(); // should be superfluous | ||||
287 | } | ||||
288 | |||||
289 | |||||
290 | void SvBaseLink::SetUpdateMode( SfxLinkUpdateMode nMode ) | ||||
291 | { | ||||
292 | if( isClientType(mnObjType) && | ||||
293 | pImplData->ClientType.nUpdateMode != nMode ) | ||||
294 | { | ||||
295 | AddNextRef(); | ||||
296 | Disconnect(); | ||||
297 | |||||
298 | pImplData->ClientType.nUpdateMode = nMode; | ||||
299 | GetRealObject_(); | ||||
300 | ReleaseRef(); | ||||
301 | } | ||||
302 | } | ||||
303 | |||||
304 | // #i88291# | ||||
305 | void SvBaseLink::clearStreamToLoadFrom() | ||||
306 | { | ||||
307 | m_xInputStreamToLoadFrom.clear(); | ||||
308 | if( xObj.is() ) | ||||
309 | { | ||||
310 | xObj->clearStreamToLoadFrom(); | ||||
311 | } | ||||
312 | } | ||||
313 | |||||
314 | bool SvBaseLink::Update() | ||||
315 | { | ||||
316 | if( isClientType(mnObjType) ) | ||||
317 | { | ||||
318 | AddNextRef(); | ||||
319 | Disconnect(); | ||||
320 | |||||
321 | GetRealObject_(); | ||||
322 | ReleaseRef(); | ||||
323 | if( xObj.is() ) | ||||
324 | { | ||||
325 | xObj->setStreamToLoadFrom(m_xInputStreamToLoadFrom,m_bIsReadOnly); | ||||
326 | OUString sMimeType( SotExchange::GetFormatMimeType( | ||||
327 | pImplData->ClientType.nCntntType )); | ||||
328 | Any aData; | ||||
329 | |||||
330 | if( xObj->GetData( aData, sMimeType ) ) | ||||
331 | { | ||||
332 | UpdateResult eRes = DataChanged(sMimeType, aData); | ||||
333 | bool bSuccess = eRes == SUCCESS; | ||||
334 | //for manual Updates there is no need to hold the ServerObject | ||||
335 | if( SvBaseLinkObjectType::ClientDde == mnObjType && | ||||
336 | SfxLinkUpdateMode::ONCALL == GetUpdateMode() && xObj.is() ) | ||||
337 | xObj->RemoveAllDataAdvise( this ); | ||||
338 | return bSuccess; | ||||
339 | } | ||||
340 | if( xObj.is() ) | ||||
341 | { | ||||
342 | // should be asynchronous? | ||||
343 | if( xObj->IsPending() ) | ||||
344 | return true; | ||||
345 | |||||
346 | // we do not need the object anymore | ||||
347 | AddNextRef(); | ||||
348 | Disconnect(); | ||||
349 | ReleaseRef(); | ||||
350 | } | ||||
351 | } | ||||
352 | } | ||||
353 | return false; | ||||
354 | } | ||||
355 | |||||
356 | |||||
357 | SfxLinkUpdateMode SvBaseLink::GetUpdateMode() const | ||||
358 | { | ||||
359 | return isClientType(mnObjType) | ||||
360 | ? pImplData->ClientType.nUpdateMode | ||||
361 | : SfxLinkUpdateMode::ONCALL; | ||||
362 | } | ||||
363 | |||||
364 | |||||
365 | void SvBaseLink::GetRealObject_( bool bConnect) | ||||
366 | { | ||||
367 | if( !pImpl->m_pLinkMgr ) | ||||
368 | return; | ||||
369 | |||||
370 | DBG_ASSERT( !xObj.is(), "object already exist" )do { if (true && (!(!xObj.is()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/lnkbase2.cxx" ":" "370" ": "), "%s", "object already exist"); } } while (false ); | ||||
371 | |||||
372 | if( SvBaseLinkObjectType::ClientDde == mnObjType ) | ||||
373 | { | ||||
374 | OUString sServer; | ||||
375 | if( sfx2::LinkManager::GetDisplayNames( this, &sServer ) && | ||||
376 | sServer == Application::GetAppName() ) // internal Link !!! | ||||
377 | { | ||||
378 | // so that the Internal link can be created! | ||||
379 | mnObjType = SvBaseLinkObjectType::Internal; | ||||
380 | xObj = sfx2::LinkManager::CreateObj( this ); | ||||
381 | |||||
382 | pImplData->ClientType.bIntrnlLnk = true; | ||||
383 | mnObjType = SvBaseLinkObjectType::ClientDde; // so we know what it once was! | ||||
384 | } | ||||
385 | else | ||||
386 | { | ||||
387 | pImplData->ClientType.bIntrnlLnk = false; | ||||
388 | xObj = sfx2::LinkManager::CreateObj( this ); | ||||
389 | } | ||||
390 | } | ||||
391 | else if( isClientType(mnObjType) ) | ||||
392 | xObj = sfx2::LinkManager::CreateObj( this ); | ||||
393 | |||||
394 | if( bConnect && ( !xObj.is() || !xObj->Connect( this ) ) ) | ||||
395 | Disconnect(); | ||||
396 | } | ||||
397 | |||||
398 | SotClipboardFormatId SvBaseLink::GetContentType() const | ||||
399 | { | ||||
400 | if( isClientType(mnObjType) ) | ||||
401 | return pImplData->ClientType.nCntntType; | ||||
402 | |||||
403 | return SotClipboardFormatId::NONE; // all Formats ? | ||||
404 | } | ||||
405 | |||||
406 | |||||
407 | void SvBaseLink::SetContentType( SotClipboardFormatId nType ) | ||||
408 | { | ||||
409 | if( isClientType(mnObjType) ) | ||||
410 | { | ||||
411 | pImplData->ClientType.nCntntType = nType; | ||||
412 | } | ||||
413 | } | ||||
414 | |||||
415 | LinkManager* SvBaseLink::GetLinkManager() | ||||
416 | { | ||||
417 | return pImpl->m_pLinkMgr; | ||||
418 | } | ||||
419 | |||||
420 | const LinkManager* SvBaseLink::GetLinkManager() const | ||||
421 | { | ||||
422 | return pImpl->m_pLinkMgr; | ||||
423 | } | ||||
424 | |||||
425 | void SvBaseLink::SetLinkManager( LinkManager* _pMgr ) | ||||
426 | { | ||||
427 | pImpl->m_pLinkMgr = _pMgr; | ||||
428 | } | ||||
429 | |||||
430 | void SvBaseLink::Disconnect() | ||||
431 | { | ||||
432 | if( xObj.is() ) | ||||
433 | { | ||||
434 | xObj->RemoveAllDataAdvise( this ); | ||||
435 | xObj->RemoveConnectAdvise( this ); | ||||
436 | xObj.clear(); | ||||
437 | } | ||||
438 | } | ||||
439 | |||||
440 | SvBaseLink::UpdateResult SvBaseLink::DataChanged( const OUString &, const css::uno::Any & ) | ||||
441 | { | ||||
442 | if ( mnObjType == SvBaseLinkObjectType::DdeExternal ) | ||||
443 | { | ||||
444 | if( pImplData->DDEType.pItem ) | ||||
445 | pImplData->DDEType.pItem->Notify(); | ||||
446 | } | ||||
447 | return SUCCESS; | ||||
448 | } | ||||
449 | |||||
450 | void SvBaseLink::Edit(weld::Window* pParent, const Link<SvBaseLink&,void>& rEndEditHdl ) | ||||
451 | { | ||||
452 | pImpl->m_pParentWin = pParent; | ||||
453 | pImpl->m_aEndEditLink = rEndEditHdl; | ||||
454 | pImpl->m_bIsConnect = xObj.is(); | ||||
455 | if( !pImpl->m_bIsConnect
| ||||
| |||||
456 | GetRealObject_( xObj.is() ); | ||||
457 | |||||
458 | bool bAsync = false; | ||||
459 | Link<const OUString&, void> aLink = LINK( this, SvBaseLink, EndEditHdl )::tools::detail::makeLink( ::tools::detail::castTo<SvBaseLink *>(this), &SvBaseLink::LinkStubEndEditHdl); | ||||
460 | |||||
461 | if( isClientType(mnObjType) && pImplData->ClientType.bIntrnlLnk ) | ||||
462 | { | ||||
463 | if( pImpl->m_pLinkMgr ) | ||||
464 | { | ||||
465 | SvLinkSourceRef ref = sfx2::LinkManager::CreateObj( this ); | ||||
466 | if( ref.is() ) | ||||
467 | { | ||||
468 | ref->Edit( pParent, this, aLink ); | ||||
469 | bAsync = true; | ||||
470 | } | ||||
471 | } | ||||
472 | } | ||||
473 | else | ||||
474 | { | ||||
475 | xObj->Edit( pParent, this, aLink ); | ||||
476 | bAsync = true; | ||||
477 | } | ||||
478 | |||||
479 | if ( !bAsync
| ||||
480 | { | ||||
481 | ExecuteEdit( OUString() ); | ||||
482 | bWasLastEditOK = false; | ||||
483 | pImpl->m_aEndEditLink.Call( *this ); | ||||
484 | } | ||||
485 | } | ||||
486 | |||||
487 | bool SvBaseLink::ExecuteEdit( const OUString& _rNewName ) | ||||
488 | { | ||||
489 | if( !_rNewName.isEmpty() ) | ||||
490 | { | ||||
491 | SetLinkSourceName( _rNewName ); | ||||
492 | if( !Update() ) | ||||
493 | { | ||||
494 | OUString sApp, sTopic, sItem, sError; | ||||
495 | sfx2::LinkManager::GetDisplayNames( this, &sApp, &sTopic, &sItem ); | ||||
496 | if( mnObjType == SvBaseLinkObjectType::ClientDde ) | ||||
497 | { | ||||
498 | sError = SfxResId(STR_DDE_ERRORreinterpret_cast<char const *>("STR_DDE_ERROR" "\004" u8"DDE link to %1 for %2 area %3 are not available." )); | ||||
499 | |||||
500 | sal_Int32 nFndPos = sError.indexOf( "%1" ); | ||||
501 | if( -1 != nFndPos ) | ||||
502 | { | ||||
503 | sError = sError.replaceAt( nFndPos, 2, sApp ); | ||||
504 | nFndPos = nFndPos + sApp.getLength(); | ||||
505 | |||||
506 | if( -1 != ( nFndPos = sError.indexOf( "%2", nFndPos ))) | ||||
507 | { | ||||
508 | sError = sError.replaceAt( nFndPos, 2, sTopic ); | ||||
509 | nFndPos = nFndPos + sTopic.getLength(); | ||||
510 | |||||
511 | if( -1 != ( nFndPos = sError.indexOf( "%3", nFndPos ))) | ||||
512 | sError = sError.replaceAt( nFndPos, 2, sItem ); | ||||
513 | } | ||||
514 | } | ||||
515 | } | ||||
516 | else | ||||
517 | return false; | ||||
518 | |||||
519 | std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pImpl->m_pParentWin, | ||||
520 | VclMessageType::Warning, VclButtonsType::Ok, sError)); | ||||
521 | xBox->run(); | ||||
522 | } | ||||
523 | } | ||||
524 | else if( !pImpl->m_bIsConnect ) | ||||
525 | Disconnect(); | ||||
526 | pImpl->m_bIsConnect = false; | ||||
527 | return true; | ||||
528 | } | ||||
529 | |||||
530 | void SvBaseLink::Closed() | ||||
531 | { | ||||
532 | if( xObj.is() ) | ||||
533 | xObj->RemoveAllDataAdvise( this ); | ||||
534 | } | ||||
535 | |||||
536 | FileDialogHelper & SvBaseLink::GetInsertFileDialog(const OUString& rFactory) const | ||||
537 | { | ||||
538 | pImpl->m_pFileDlg.reset( new FileDialogHelper( | ||||
539 | ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, | ||||
540 | FileDialogFlags::Insert, rFactory, SfxFilterFlags::NONE, SfxFilterFlags::NONE, pImpl->m_pParentWin) ); | ||||
541 | return *pImpl->m_pFileDlg; | ||||
542 | } | ||||
543 | |||||
544 | ImplDdeItem::~ImplDdeItem() | ||||
545 | { | ||||
546 | bIsInDTOR = true; | ||||
547 | // So that no-one gets the idea to delete the pointer when Disconnecting! | ||||
548 | tools::SvRef<SvBaseLink> aRef( pLink ); | ||||
549 | aRef->Disconnect(); | ||||
550 | } | ||||
551 | |||||
552 | DdeData* ImplDdeItem::Get( SotClipboardFormatId nFormat ) | ||||
553 | { | ||||
554 | if( pLink->GetObj() ) | ||||
555 | { | ||||
556 | // is it still valid? | ||||
557 | if( bIsValidData && nFormat == aData.GetFormat() ) | ||||
558 | return &aData; | ||||
559 | |||||
560 | Any aValue; | ||||
561 | OUString sMimeType( SotExchange::GetFormatMimeType( nFormat )); | ||||
562 | if( pLink->GetObj()->GetData( aValue, sMimeType ) ) | ||||
563 | { | ||||
564 | if( aValue >>= aSeq ) | ||||
565 | { | ||||
566 | aData = DdeData( aSeq.getConstArray(), aSeq.getLength(), nFormat ); | ||||
567 | |||||
568 | bIsValidData = true; | ||||
569 | return &aData; | ||||
570 | } | ||||
571 | } | ||||
572 | } | ||||
573 | aSeq.realloc( 0 ); | ||||
574 | bIsValidData = false; | ||||
575 | return nullptr; | ||||
576 | } | ||||
577 | |||||
578 | |||||
579 | bool ImplDdeItem::Put( const DdeData* ) | ||||
580 | { | ||||
581 | OSL_FAIL( "ImplDdeItem::Put not implemented" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/lnkbase2.cxx" ":" "581" ": "), "%s", "ImplDdeItem::Put not implemented"); } } while (false); | ||||
582 | return false; | ||||
583 | } | ||||
584 | |||||
585 | |||||
586 | void ImplDdeItem::AdviseLoop( bool bOpen ) | ||||
587 | { | ||||
588 | // Connection is closed, so also unsubscribe link | ||||
589 | if( !pLink->GetObj() ) | ||||
590 | return; | ||||
591 | |||||
592 | if( bOpen ) | ||||
593 | { | ||||
594 | // A connection is re-established | ||||
595 | if( SvBaseLinkObjectType::DdeExternal == pLink->GetObjType() ) | ||||
596 | { | ||||
597 | pLink->GetObj()->AddDataAdvise( pLink, "text/plain;charset=utf-16", ADVISEMODE_NODATA0x01 ); | ||||
598 | pLink->GetObj()->AddConnectAdvise( pLink ); | ||||
599 | } | ||||
600 | } | ||||
601 | else | ||||
602 | { | ||||
603 | // So that no-one gets the idea to delete the pointer | ||||
604 | // when Disconnecting! | ||||
605 | tools::SvRef<SvBaseLink> aRef( pLink ); | ||||
606 | aRef->Disconnect(); | ||||
607 | } | ||||
608 | } | ||||
609 | |||||
610 | } | ||||
611 | |||||
612 | /* 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: */ |