File: | home/maarten/src/libreoffice/core/sfx2/source/appl/lnkbase2.cxx |
Warning: | line 492, column 14 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: */ |