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 <comphelper/string.hxx>
21 : #include <sfx2/linkmgr.hxx>
22 : #include <com/sun/star/document/UpdateDocMode.hpp>
23 : #include <sfx2/objsh.hxx>
24 : #include <svl/urihelper.hxx>
25 : #include <sot/formats.hxx>
26 : #include <tools/urlobj.hxx>
27 : #include <sot/exchange.hxx>
28 : #include <tools/debug.hxx>
29 : #include <vcl/msgbox.hxx>
30 : #include <sfx2/lnkbase.hxx>
31 : #include <sfx2/app.hxx>
32 : #include <vcl/graph.hxx>
33 : #include <svl/stritem.hxx>
34 : #include <svl/eitem.hxx>
35 : #include <svl/intitem.hxx>
36 : #include <unotools/localfilehelper.hxx>
37 : #include <i18nlangtag/languagetag.hxx>
38 : #include <sfx2/request.hxx>
39 : #include <vcl/dibtools.hxx>
40 : #include "unotools/charclass.hxx"
41 :
42 : #include "fileobj.hxx"
43 : #include "impldde.hxx"
44 : #include "app.hrc"
45 : #include <sfx2/sfxresid.hxx>
46 :
47 : #include <com/sun/star/lang/XComponent.hpp>
48 : #include <com/sun/star/util/XCloseable.hpp>
49 :
50 : using ::com::sun::star::uno::UNO_QUERY;
51 : using ::com::sun::star::uno::Reference;
52 : using ::com::sun::star::lang::XComponent;
53 : using ::com::sun::star::util::XCloseable;
54 :
55 : namespace sfx2
56 : {
57 :
58 10 : class SvxInternalLink : public sfx2::SvLinkSource
59 : {
60 : public:
61 5 : SvxInternalLink() {}
62 :
63 : virtual bool Connect( sfx2::SvBaseLink* ) SAL_OVERRIDE;
64 : };
65 :
66 :
67 4061 : LinkManager::LinkManager(SfxObjectShell* p)
68 4061 : : pPersist( p )
69 : {
70 4061 : }
71 :
72 :
73 8078 : LinkManager::~LinkManager()
74 : {
75 4039 : for( size_t n = 0; n < aLinkTbl.size(); ++n)
76 : {
77 0 : SvBaseLinkRef* pTmp = aLinkTbl[ n ];
78 0 : if( pTmp->Is() )
79 : {
80 0 : (*pTmp)->Disconnect();
81 0 : (*pTmp)->SetLinkManager( NULL );
82 : }
83 0 : delete pTmp;
84 : }
85 4039 : }
86 :
87 0 : void LinkManager::InsertCachedComp(const Reference<XComponent>& xComp)
88 : {
89 0 : maCachedComps.push_back(xComp);
90 0 : }
91 :
92 15 : void LinkManager::CloseCachedComps()
93 : {
94 15 : CompVector::iterator itr = maCachedComps.begin(), itrEnd = maCachedComps.end();
95 15 : for (; itr != itrEnd; ++itr)
96 : {
97 0 : Reference<XCloseable> xCloseable(*itr, UNO_QUERY);
98 0 : if (!xCloseable.is())
99 0 : continue;
100 :
101 0 : xCloseable->close(true);
102 0 : }
103 15 : maCachedComps.clear();
104 15 : }
105 :
106 :
107 :
108 48 : void LinkManager::Remove( SvBaseLink *pLink )
109 : {
110 : // No duplicate links inserted
111 48 : bool bFound = false;
112 96 : for( size_t n = 0; n < aLinkTbl.size(); )
113 : {
114 30 : SvBaseLinkRef* pTmp = aLinkTbl[ n ];
115 30 : if( pLink == *pTmp )
116 : {
117 30 : (*pTmp)->Disconnect();
118 30 : (*pTmp)->SetLinkManager( NULL );
119 30 : (*pTmp).Clear();
120 30 : bFound = true;
121 : }
122 :
123 : // Remove empty ones if they exist
124 30 : if( !pTmp->Is() )
125 : {
126 30 : delete pTmp;
127 30 : aLinkTbl.erase( aLinkTbl.begin() + n );
128 30 : if( bFound )
129 78 : return ;
130 : }
131 : else
132 0 : ++n;
133 : }
134 : }
135 :
136 :
137 30 : void LinkManager::Remove( size_t nPos, size_t nCnt )
138 : {
139 30 : if( nCnt && nPos < aLinkTbl.size() )
140 : {
141 30 : if (sal::static_int_cast<size_t>(nPos + nCnt) > aLinkTbl.size())
142 0 : nCnt = aLinkTbl.size() - nPos;
143 :
144 64 : for( size_t n = nPos; n < nPos + nCnt; ++n)
145 : {
146 34 : SvBaseLinkRef* pTmp = aLinkTbl[ n ];
147 34 : if( pTmp->Is() )
148 : {
149 34 : (*pTmp)->Disconnect();
150 34 : (*pTmp)->SetLinkManager( NULL );
151 : }
152 34 : delete pTmp;
153 : }
154 30 : aLinkTbl.erase( aLinkTbl.begin() + nPos, aLinkTbl.begin() + nPos + nCnt );
155 : }
156 30 : }
157 :
158 :
159 65 : bool LinkManager::Insert( SvBaseLink* pLink )
160 : {
161 73 : for( size_t n = 0; n < aLinkTbl.size(); ++n )
162 : {
163 8 : SvBaseLinkRef* pTmp = aLinkTbl[ n ];
164 8 : if( !pTmp->Is() )
165 : {
166 0 : delete pTmp;
167 0 : aLinkTbl.erase( aLinkTbl.begin() + n-- );
168 : }
169 8 : else if( pLink == *pTmp )
170 0 : return false; // No duplicate links inserted
171 : }
172 :
173 65 : SvBaseLinkRef* pTmp = new SvBaseLinkRef( pLink );
174 65 : pLink->SetLinkManager( this );
175 65 : aLinkTbl.push_back( pTmp );
176 65 : return true;
177 : }
178 :
179 :
180 62 : bool LinkManager::InsertLink( SvBaseLink * pLink,
181 : sal_uInt16 nObjType,
182 : SfxLinkUpdateMode nUpdateMode,
183 : const OUString* pName )
184 : {
185 : // This First
186 62 : pLink->SetObjType( nObjType );
187 62 : if( pName )
188 62 : pLink->SetName( *pName );
189 62 : pLink->SetUpdateMode( nUpdateMode );
190 62 : return Insert( pLink );
191 : }
192 :
193 :
194 3 : bool LinkManager::InsertDDELink( SvBaseLink * pLink,
195 : const OUString& rServer,
196 : const OUString& rTopic,
197 : const OUString& rItem )
198 : {
199 3 : if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
200 0 : return false;
201 :
202 3 : OUString sCmd;
203 3 : ::sfx2::MakeLnkName( sCmd, &rServer, rTopic, rItem );
204 :
205 3 : pLink->SetObjType( OBJECT_CLIENT_DDE );
206 3 : pLink->SetName( sCmd );
207 3 : return Insert( pLink );
208 : }
209 :
210 :
211 0 : bool LinkManager::InsertDDELink( SvBaseLink * pLink )
212 : {
213 : DBG_ASSERT( OBJECT_CLIENT_SO & pLink->GetObjType(), "no OBJECT_CLIENT_SO" );
214 0 : if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
215 0 : return false;
216 :
217 0 : if( pLink->GetObjType() == OBJECT_CLIENT_SO )
218 0 : pLink->SetObjType( OBJECT_CLIENT_DDE );
219 :
220 0 : return Insert( pLink );
221 : }
222 :
223 :
224 : // Obtain the string for the dialog
225 145 : bool LinkManager::GetDisplayNames( const SvBaseLink * pLink,
226 : OUString* pType,
227 : OUString* pFile,
228 : OUString* pLinkStr,
229 : OUString* pFilter )
230 : {
231 145 : bool bRet = false;
232 145 : const OUString sLNm( pLink->GetLinkSourceName() );
233 145 : if( !sLNm.isEmpty() )
234 : {
235 145 : switch( pLink->GetObjType() )
236 : {
237 : case OBJECT_CLIENT_FILE:
238 : case OBJECT_CLIENT_GRF:
239 : case OBJECT_CLIENT_OLE:
240 : {
241 135 : sal_Int32 nPos = 0;
242 135 : OUString sFile( sLNm.getToken( 0, ::sfx2::cTokenSeparator, nPos ) );
243 270 : OUString sRange( sLNm.getToken( 0, ::sfx2::cTokenSeparator, nPos ) );
244 :
245 135 : if( pFile )
246 134 : *pFile = sFile;
247 135 : if( pLinkStr )
248 27 : *pLinkStr = sRange;
249 135 : if( pFilter )
250 99 : *pFilter = nPos == -1 ? OUString() : sLNm.copy(nPos);
251 :
252 135 : if( pType )
253 : {
254 5 : sal_uInt16 nObjType = pLink->GetObjType();
255 15 : *pType = SfxResId(
256 0 : ( OBJECT_CLIENT_FILE == nObjType || OBJECT_CLIENT_OLE == nObjType )
257 : ? RID_SVXSTR_FILELINK
258 5 : : RID_SVXSTR_GRAFIKLINK).toString();
259 : }
260 270 : bRet = true;
261 : }
262 135 : break;
263 : case OBJECT_CLIENT_DDE:
264 : {
265 10 : sal_Int32 nTmp = 0;
266 10 : OUString sCmd( sLNm );
267 20 : OUString sServer( sCmd.getToken( 0, cTokenSeparator, nTmp ) );
268 20 : OUString sTopic( sCmd.getToken( 0, cTokenSeparator, nTmp ) );
269 :
270 10 : if( pType )
271 5 : *pType = sServer;
272 10 : if( pFile )
273 5 : *pFile = sTopic;
274 10 : if( pLinkStr )
275 5 : *pLinkStr = sCmd.copy( nTmp );
276 20 : bRet = true;
277 : }
278 10 : break;
279 : default:
280 0 : break;
281 : }
282 : }
283 :
284 145 : return bRet;
285 : }
286 :
287 3 : void LinkManager::UpdateAllLinks(
288 : bool bAskUpdate,
289 : bool /*bCallErrHdl*/,
290 : bool bUpdateGrfLinks,
291 : vcl::Window* pParentWin )
292 : {
293 : // First make a copy of the array in order to update links
294 : // links in ... no contact between them!
295 3 : std::vector<SvBaseLink*> aTmpArr;
296 6 : for( size_t n = 0; n < aLinkTbl.size(); ++n )
297 : {
298 3 : SvBaseLink* pLink = *aLinkTbl[ n ];
299 3 : if( !pLink )
300 : {
301 0 : Remove( n-- );
302 0 : continue;
303 : }
304 3 : aTmpArr.push_back( pLink );
305 : }
306 :
307 6 : for( size_t n = 0; n < aTmpArr.size(); ++n )
308 : {
309 3 : SvBaseLink* pLink = aTmpArr[ n ];
310 :
311 : // search first in the array after the entry
312 3 : bool bFound = false;
313 3 : for( size_t i = 0; i < aLinkTbl.size(); ++i )
314 3 : if( pLink == *aLinkTbl[ i ] )
315 : {
316 3 : bFound = true;
317 3 : break;
318 : }
319 :
320 3 : if( !bFound )
321 0 : continue; // was not available!
322 :
323 : // Graphic-Links not to update yet
324 9 : if( !pLink->IsVisible() ||
325 6 : ( !bUpdateGrfLinks && OBJECT_CLIENT_GRF == pLink->GetObjType() ))
326 3 : continue;
327 :
328 0 : if( bAskUpdate )
329 : {
330 0 : int nRet = ScopedVclPtr<QueryBox>::Create( pParentWin, WB_YES_NO | WB_DEF_YES, SfxResId( STR_QUERY_UPDATE_LINKS ).toString() )->Execute();
331 0 : if( RET_YES != nRet )
332 : {
333 0 : SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
334 :
335 0 : if(pShell)
336 : {
337 0 : comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = pShell->getEmbeddedObjectContainer();
338 0 : rEmbeddedObjectContainer.setUserAllowsLinkUpdate(false);
339 : }
340 :
341 3 : return ; // nothing should be updated
342 : }
343 0 : bAskUpdate = false; // once is enough
344 : }
345 :
346 0 : pLink->Update();
347 : }
348 3 : CloseCachedComps();
349 : }
350 :
351 :
352 :
353 69 : SvLinkSourceRef LinkManager::CreateObj( SvBaseLink * pLink )
354 : {
355 69 : switch( pLink->GetObjType() )
356 : {
357 : case OBJECT_CLIENT_FILE:
358 : case OBJECT_CLIENT_GRF:
359 : case OBJECT_CLIENT_OLE:
360 64 : return new SvFileObject;
361 : case OBJECT_INTERN:
362 5 : return new SvxInternalLink;
363 : case OBJECT_CLIENT_DDE:
364 0 : return new SvDDEObject;
365 : default:
366 0 : return SvLinkSourceRef();
367 : }
368 : }
369 :
370 6 : bool LinkManager::InsertServer( SvLinkSource* pObj )
371 : {
372 : // no duplicate inserts
373 6 : if( !pObj )
374 0 : return false;
375 :
376 6 : return aServerTbl.insert( pObj ).second;
377 : }
378 :
379 :
380 5 : void LinkManager::RemoveServer( SvLinkSource* pObj )
381 : {
382 5 : aServerTbl.erase( pObj );
383 5 : }
384 :
385 :
386 3 : void MakeLnkName( OUString& rName, const OUString* pType, const OUString& rFile,
387 : const OUString& rLink, const OUString* pFilter )
388 : {
389 3 : if( pType )
390 : {
391 3 : rName = comphelper::string::strip(*pType, ' ');
392 3 : rName += OUString(cTokenSeparator);
393 : }
394 0 : else if( !rName.isEmpty() )
395 0 : rName.clear();
396 :
397 3 : rName += rFile;
398 :
399 3 : rName = comphelper::string::strip(rName, ' ');
400 3 : rName += OUString(cTokenSeparator);
401 3 : rName = comphelper::string::strip(rName, ' ');
402 3 : rName += rLink;
403 3 : if( pFilter )
404 : {
405 0 : rName += OUString(cTokenSeparator);
406 0 : rName += *pFilter;
407 0 : rName = comphelper::string::strip(rName, ' ');
408 : }
409 3 : }
410 :
411 760 : void LinkManager::ReconnectDdeLink(SfxObjectShell& rServer)
412 : {
413 760 : SfxMedium* pMed = rServer.GetMedium();
414 760 : if (!pMed)
415 760 : return;
416 :
417 760 : const ::sfx2::SvBaseLinks& rLinks = GetLinks();
418 760 : size_t n = rLinks.size();
419 :
420 765 : for (size_t i = 0; i < n; ++i)
421 : {
422 5 : ::sfx2::SvBaseLink* p = *rLinks[i];
423 5 : OUString aType, aFile, aLink, aFilter;
424 5 : if (!GetDisplayNames(p, &aType, &aFile, &aLink, &aFilter))
425 0 : continue;
426 :
427 5 : if (aType != "soffice")
428 : // DDE connections between OOo apps are always named 'soffice'.
429 5 : continue;
430 :
431 0 : OUString aTmp;
432 0 : OUString aURL = aFile;
433 0 : if (utl::LocalFileHelper::ConvertPhysicalNameToURL(aFile, aTmp))
434 0 : aURL = aTmp;
435 :
436 0 : if (!aURL.equalsIgnoreAsciiCase(pMed->GetName()))
437 : // This DDE link is not associated with this server shell... Skip it.
438 0 : continue;
439 :
440 0 : if (aLink.isEmpty())
441 0 : continue;
442 :
443 0 : LinkServerShell(aLink, rServer, *p);
444 0 : }
445 : }
446 :
447 0 : void LinkManager::LinkServerShell(const OUString& rPath, SfxObjectShell& rServer, ::sfx2::SvBaseLink& rLink)
448 : {
449 0 : ::sfx2::SvLinkSource* pSrvSrc = rServer.DdeCreateLinkSource(rPath);
450 0 : if (pSrvSrc)
451 : {
452 0 : ::com::sun::star::datatransfer::DataFlavor aFl;
453 0 : SotExchange::GetFormatDataFlavor(rLink.GetContentType(), aFl);
454 0 : rLink.SetObj(pSrvSrc);
455 : pSrvSrc->AddDataAdvise(
456 : &rLink, aFl.MimeType,
457 0 : SfxLinkUpdateMode::ONCALL == rLink.GetUpdateMode() ? ADVISEMODE_ONLYONCE : 0);
458 : }
459 0 : }
460 :
461 62 : bool LinkManager::InsertFileLink(
462 : sfx2::SvBaseLink& rLink, sal_uInt16 nFileType, const OUString& rFileNm,
463 : const OUString* pFilterNm, const OUString* pRange)
464 : {
465 62 : if (!(OBJECT_CLIENT_SO & rLink.GetObjType()))
466 0 : return false;
467 :
468 62 : OUStringBuffer aBuf;
469 62 : aBuf.append(rFileNm);
470 62 : aBuf.append(sfx2::cTokenSeparator);
471 :
472 62 : if (pRange)
473 18 : aBuf.append(*pRange);
474 :
475 62 : if (pFilterNm)
476 : {
477 48 : aBuf.append(sfx2::cTokenSeparator);
478 48 : aBuf.append(*pFilterNm);
479 : }
480 :
481 124 : OUString aCmd = aBuf.makeStringAndClear();
482 124 : return InsertLink(&rLink, nFileType, SfxLinkUpdateMode::ONCALL, &aCmd);
483 : }
484 :
485 : // A transfer is aborted, so cancel all download media
486 : // (for now this is only of interest for the file links!)
487 2699 : void LinkManager::CancelTransfers()
488 : {
489 : SvFileObject* pFileObj;
490 : sfx2::SvBaseLink* pLnk;
491 :
492 2699 : const sfx2::SvBaseLinks& rLnks = GetLinks();
493 5412 : for( size_t n = rLnks.size(); n; )
494 42 : if( 0 != ( pLnk = &(*rLnks[ --n ])) &&
495 42 : OBJECT_CLIENT_FILE == (OBJECT_CLIENT_FILE & pLnk->GetObjType()) &&
496 : 0 != ( pFileObj = static_cast<SvFileObject*>(pLnk->GetObj()) ) )
497 14 : pFileObj->CancelTransfers();
498 2699 : }
499 : // For the purpose of sending Status information from the file object to
500 : // the base link, there exist a dedicated ClipBoardId. The SvData-object
501 : // gets the appropriate information as a string
502 : // For now this is required for file object in conjunction with JavaScript
503 : // - needs information about Load/Abort/Error
504 52 : SotClipboardFormatId LinkManager::RegisterStatusInfoId()
505 : {
506 : static SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
507 :
508 52 : if( nFormat == SotClipboardFormatId::NONE )
509 : {
510 : nFormat = SotExchange::RegisterFormatName(
511 4 : OUString("StatusInfo from SvxInternalLink"));
512 : }
513 52 : return nFormat;
514 : }
515 :
516 :
517 :
518 37 : bool LinkManager::GetGraphicFromAny( const OUString& rMimeType,
519 : const ::com::sun::star::uno::Any & rValue,
520 : Graphic& rGrf )
521 : {
522 37 : bool bRet = false;
523 37 : ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
524 37 : if( rValue.hasValue() && ( rValue >>= aSeq ) )
525 : {
526 48 : SvMemoryStream aMemStm( const_cast<sal_Int8 *>(aSeq.getConstArray()), aSeq.getLength(),
527 48 : StreamMode::READ );
528 24 : aMemStm.Seek( 0 );
529 :
530 24 : switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
531 : {
532 : case SotClipboardFormatId::SVXB:
533 : {
534 24 : ReadGraphic( aMemStm, rGrf );
535 24 : bRet = true;
536 : }
537 24 : break;
538 : case SotClipboardFormatId::GDIMETAFILE:
539 : {
540 0 : GDIMetaFile aMtf;
541 0 : aMtf.Read( aMemStm );
542 0 : rGrf = aMtf;
543 0 : bRet = true;
544 : }
545 0 : break;
546 : case SotClipboardFormatId::BITMAP:
547 : {
548 0 : Bitmap aBmp;
549 0 : ReadDIB(aBmp, aMemStm, true);
550 0 : rGrf = aBmp;
551 0 : bRet = true;
552 : }
553 0 : break;
554 0 : default: break;
555 24 : }
556 : }
557 37 : return bRet;
558 : }
559 :
560 :
561 :
562 20 : OUString lcl_DDE_RelToAbs( const OUString& rTopic, const OUString& rBaseURL )
563 : {
564 20 : OUString sRet;
565 40 : INetURLObject aURL( rTopic );
566 20 : if( INetProtocol::NotValid == aURL.GetProtocol() )
567 20 : utl::LocalFileHelper::ConvertSystemPathToURL( rTopic, rBaseURL, sRet );
568 20 : if( sRet.isEmpty() )
569 20 : sRet = URIHelper::SmartRel2Abs( INetURLObject(rBaseURL), rTopic, URIHelper::GetMaybeFileHdl(), true );
570 40 : return sRet;
571 : }
572 :
573 5 : bool SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
574 : {
575 5 : SfxObjectShell* pFndShell = 0;
576 5 : sal_uInt16 nUpdateMode = com::sun::star::document::UpdateDocMode::NO_UPDATE;
577 10 : OUString sTopic, sItem, sReferer;
578 5 : LinkManager* pLinkMgr = pLink->GetLinkManager();
579 5 : if (pLinkMgr && sfx2::LinkManager::GetDisplayNames(pLink, 0, &sTopic, &sItem) && !sTopic.isEmpty())
580 : {
581 : // first only loop over the DocumentShells the shells and find those
582 : // with the name:
583 5 : CharClass aCC( LanguageTag( LANGUAGE_SYSTEM) );
584 :
585 5 : TypeId aType( TYPE(SfxObjectShell) );
586 :
587 5 : bool bFirst = true;
588 5 : SfxObjectShell* pShell = pLinkMgr->GetPersist();
589 5 : if( pShell && pShell->GetMedium() )
590 : {
591 5 : sReferer = pShell->GetMedium()->GetBaseURL();
592 5 : SFX_ITEMSET_ARG( pShell->GetMedium()->GetItemSet(), pItem, SfxUInt16Item, SID_UPDATEDOCMODE, false );
593 5 : if ( pItem )
594 5 : nUpdateMode = pItem->GetValue();
595 : }
596 :
597 10 : OUString sNmURL(aCC.lowercase(lcl_DDE_RelToAbs(sTopic, sReferer)));
598 :
599 5 : if ( !pShell )
600 : {
601 0 : bFirst = false;
602 0 : pShell = SfxObjectShell::GetFirst( &aType, false );
603 : }
604 :
605 10 : OUString sTmp;
606 20 : while( pShell )
607 : {
608 15 : if( sTmp.isEmpty() )
609 : {
610 15 : sTmp = pShell->GetTitle( SFX_TITLE_FULLNAME );
611 15 : sTmp = lcl_DDE_RelToAbs(sTmp, sReferer );
612 : }
613 :
614 :
615 15 : sTmp = aCC.lowercase( sTmp );
616 15 : if( sTmp == sNmURL ) // we want these
617 : {
618 5 : pFndShell = pShell;
619 5 : break;
620 : }
621 :
622 10 : if( bFirst )
623 : {
624 5 : bFirst = false;
625 5 : pShell = SfxObjectShell::GetFirst( &aType, false );
626 : }
627 : else
628 5 : pShell = SfxObjectShell::GetNext( *pShell, &aType, false );
629 :
630 10 : sTmp.clear();
631 5 : }
632 : }
633 :
634 : // empty topics are not allowed - which document is it
635 5 : if( sTopic.isEmpty() )
636 0 : return false;
637 :
638 5 : if (pFndShell)
639 : {
640 5 : sfx2::SvLinkSource* pNewSrc = pFndShell->DdeCreateLinkSource( sItem );
641 5 : if( pNewSrc )
642 : {
643 5 : ::com::sun::star::datatransfer::DataFlavor aFl;
644 5 : SotExchange::GetFormatDataFlavor( pLink->GetContentType(), aFl );
645 :
646 5 : pLink->SetObj( pNewSrc );
647 : pNewSrc->AddDataAdvise( pLink, aFl.MimeType,
648 5 : SfxLinkUpdateMode::ONCALL == pLink->GetUpdateMode()
649 : ? ADVISEMODE_ONLYONCE
650 5 : : 0 );
651 5 : return true;
652 : }
653 : }
654 : else
655 : {
656 : // then try to download the file:
657 0 : INetURLObject aURL( sTopic );
658 0 : INetProtocol eOld = aURL.GetProtocol();
659 0 : aURL.SetURL( sTopic = lcl_DDE_RelToAbs( sTopic, sReferer ) );
660 0 : if( INetProtocol::NotValid != eOld ||
661 0 : INetProtocol::Http != aURL.GetProtocol() )
662 : {
663 0 : SfxStringItem aName( SID_FILE_NAME, sTopic );
664 0 : SfxBoolItem aMinimized(SID_MINIMIZED, true);
665 0 : SfxBoolItem aHidden(SID_HIDDEN, true);
666 0 : SfxStringItem aTarget( SID_TARGETNAME, OUString("_blank") );
667 0 : SfxStringItem aReferer( SID_REFERER, sReferer );
668 0 : SfxUInt16Item aUpdate( SID_UPDATEDOCMODE, nUpdateMode );
669 0 : SfxBoolItem aReadOnly(SID_DOC_READONLY, false);
670 :
671 : // Disable automatic re-connection to avoid this link instance
672 : // being destroyed at re-connection.
673 0 : SfxBoolItem aDdeConnect(SID_DDE_RECONNECT_ONLOAD, false);
674 :
675 : // #i14200# (DDE-link crashes wordprocessor)
676 0 : SfxAllItemSet aArgs( SfxGetpApp()->GetPool() );
677 0 : aArgs.Put(aReferer);
678 0 : aArgs.Put(aTarget);
679 0 : aArgs.Put(aHidden);
680 0 : aArgs.Put(aMinimized);
681 0 : aArgs.Put(aName);
682 0 : aArgs.Put(aUpdate);
683 0 : aArgs.Put(aReadOnly);
684 0 : aArgs.Put(aDdeConnect);
685 0 : Reference<XComponent> xComp = SfxObjectShell::CreateAndLoadComponent(aArgs);
686 0 : pFndShell = SfxObjectShell::GetShellFromComponent(xComp);
687 0 : if (xComp.is() && pFndShell)
688 : {
689 0 : pLinkMgr->InsertCachedComp(xComp);
690 0 : sfx2::LinkManager::LinkServerShell(sItem, *pFndShell, *pLink);
691 0 : return true;
692 0 : }
693 0 : }
694 : }
695 :
696 5 : return false;
697 : }
698 :
699 :
700 : }
701 :
702 :
703 :
704 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|