1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sfx2.hxx"
24
25 #include <sfx2/linkmgr.hxx>
26 #include <com/sun/star/document/UpdateDocMode.hpp>
27 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28 #include <com/sun/star/util/XURLTransformer.hpp>
29
30 #include <sfx2/objsh.hxx>
31 #include <svl/urihelper.hxx>
32 #include <sot/formats.hxx>
33 #include <tools/urlobj.hxx>
34 #include <sot/exchange.hxx>
35 #include <tools/debug.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <sfx2/lnkbase.hxx>
38 #include <sfx2/app.hxx>
39 #include <vcl/graph.hxx>
40 #include <svl/stritem.hxx>
41 #include <svl/eitem.hxx>
42 #include <svl/intitem.hxx>
43 #include <unotools/localfilehelper.hxx>
44 #include <svtools/linkpolicy.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <i18npool/mslangid.hxx>
47 #include <sfx2/request.hxx>
48 #include <vcl/dibtools.hxx>
49
50 #include "fileobj.hxx"
51 #include "impldde.hxx"
52 #include "app.hrc"
53 #include "sfx2/sfxresid.hxx"
54
55 #define _SVSTDARR_STRINGSDTOR
56 #include <svl/svstdarr.hxx>
57
58 namespace sfx2
59 {
60
61 class SvxInternalLink : public sfx2::SvLinkSource
62 {
63 public:
SvxInternalLink()64 SvxInternalLink() {}
65
66 virtual sal_Bool Connect( sfx2::SvBaseLink* );
67 };
68
69
SV_IMPL_PTRARR(SvBaseLinks,SvBaseLinkRefPtr)70 SV_IMPL_PTRARR( SvBaseLinks, SvBaseLinkRefPtr )
71
72 LinkManager::LinkManager(SfxObjectShell* p)
73 : pPersist(p),
74 mAutoAskUpdateAllLinks(sal_False),
75 mUpdateAsked(sal_False)
76 {
77 }
78
~LinkManager()79 LinkManager::~LinkManager()
80 {
81 SvBaseLinkRef** ppRef = (SvBaseLinkRef**)aLinkTbl.GetData();
82 for( sal_uInt16 n = aLinkTbl.Count(); n; --n, ++ppRef )
83 {
84 if( (*ppRef)->Is() )
85 {
86 (*(*ppRef))->Disconnect();
87 (*(*ppRef))->SetLinkManager( NULL );
88 }
89 delete *ppRef;
90 }
91 }
92
93
94 /************************************************************************
95 |* LinkManager::Remove()
96 |*
97 |* Description
98 *************************************************************************/
99
Remove(SvBaseLink * pLink)100 void LinkManager::Remove( SvBaseLink *pLink )
101 {
102 // do not insert links double
103 int bFound = sal_False;
104 SvBaseLinkRef** ppRef = (SvBaseLinkRef**)aLinkTbl.GetData();
105 for( sal_uInt16 n = aLinkTbl.Count(); n; --n, ++ppRef )
106 {
107 if( pLink == *(*ppRef) )
108 {
109 (*(*ppRef))->Disconnect();
110 (*(*ppRef))->SetLinkManager( NULL );
111 (*(*ppRef)).Clear();
112 bFound = sal_True;
113 }
114
115 // if there are still some empty ones, get rid of them
116 if( !(*ppRef)->Is() )
117 {
118 delete *ppRef;
119 aLinkTbl.Remove( aLinkTbl.Count() - n, 1 );
120 if( bFound )
121 return ;
122 --ppRef;
123 }
124 }
125 }
126
127
Remove(sal_uInt16 nPos,sal_uInt16 nCnt)128 void LinkManager::Remove( sal_uInt16 nPos, sal_uInt16 nCnt )
129 {
130 if( nCnt && nPos < aLinkTbl.Count() )
131 {
132 if( nPos + nCnt > aLinkTbl.Count() )
133 nCnt = aLinkTbl.Count() - nPos;
134
135 SvBaseLinkRef** ppRef = (SvBaseLinkRef**)aLinkTbl.GetData() + nPos;
136 for( sal_uInt16 n = nCnt; n; --n, ++ppRef )
137 {
138 if( (*ppRef)->Is() )
139 {
140 (*(*ppRef))->Disconnect();
141 (*(*ppRef))->SetLinkManager( NULL );
142 }
143 delete *ppRef;
144 }
145 aLinkTbl.Remove( nPos, nCnt );
146 }
147 }
148
149
Insert(SvBaseLink * pLink)150 sal_Bool LinkManager::Insert( SvBaseLink* pLink )
151 {
152
153 // do not insert links double
154 for( sal_uInt16 n = 0; n < aLinkTbl.Count(); ++n )
155 {
156 SvBaseLinkRef* pTmp = aLinkTbl[ n ];
157 if( !pTmp->Is() )
158 aLinkTbl.DeleteAndDestroy( n-- );
159
160 if( pLink == *pTmp )
161 return sal_False;
162 }
163
164 SvBaseLinkRef* pTmp = new SvBaseLinkRef( pLink );
165 pLink->SetLinkManager( this );
166 aLinkTbl.Insert( pTmp, aLinkTbl.Count() );
167 if (mAutoAskUpdateAllLinks)
168 {
169 Window *parent = NULL;
170 SfxObjectShell* persist = GetPersist();
171 if (persist != NULL)
172 parent = GetPersist()->GetDialogParent();
173
174 SetUserAllowsLinkUpdate(pLink, GetUserAllowsLinkUpdate(parent));
175 }
176
177 return sal_True;
178 }
179
180
InsertLink(SvBaseLink * pLink,sal_uInt16 nObjType,sal_uInt16 nUpdateMode,const String * pName)181 sal_Bool LinkManager::InsertLink( SvBaseLink * pLink,
182 sal_uInt16 nObjType,
183 sal_uInt16 nUpdateMode,
184 const String* pName )
185 {
186 // in any case: do this first
187 pLink->SetObjType( nObjType );
188 if( pName )
189 pLink->SetName( *pName );
190 pLink->SetUpdateMode( nUpdateMode );
191 return Insert( pLink );
192 }
193
194
InsertDDELink(SvBaseLink * pLink,const String & rServer,const String & rTopic,const String & rItem)195 sal_Bool LinkManager::InsertDDELink( SvBaseLink * pLink,
196 const String& rServer,
197 const String& rTopic,
198 const String& rItem )
199 {
200 if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
201 return sal_False;
202
203 String sCmd;
204 ::sfx2::MakeLnkName( sCmd, &rServer, rTopic, rItem );
205
206 pLink->SetObjType( OBJECT_CLIENT_DDE );
207 pLink->SetName( sCmd );
208 return Insert( pLink );
209 }
210
211
InsertDDELink(SvBaseLink * pLink)212 sal_Bool LinkManager::InsertDDELink( SvBaseLink * pLink )
213 {
214 DBG_ASSERT( OBJECT_CLIENT_SO & pLink->GetObjType(), "no OBJECT_CLIENT_SO" );
215 if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
216 return sal_False;
217
218 if( pLink->GetObjType() == OBJECT_CLIENT_SO )
219 pLink->SetObjType( OBJECT_CLIENT_DDE );
220
221 return Insert( pLink );
222 }
223
224
225 // ask for the strings to be used in the dialog
GetDisplayNames(const SvBaseLink * pLink,String * pType,String * pFile,String * pLinkStr,String * pFilter) const226 sal_Bool LinkManager::GetDisplayNames( const SvBaseLink * pLink,
227 String* pType,
228 String* pFile,
229 String* pLinkStr,
230 String* pFilter ) const
231 {
232 sal_Bool bRet = sal_False;
233 const String sLNm( pLink->GetLinkSourceName() );
234 if( sLNm.Len() )
235 {
236 switch( pLink->GetObjType() )
237 {
238 case OBJECT_CLIENT_FILE:
239 case OBJECT_CLIENT_GRF:
240 case OBJECT_CLIENT_OLE:
241 {
242 sal_uInt16 nPos = 0;
243 String sFile( sLNm.GetToken( 0, ::sfx2::cTokenSeperator, nPos ) );
244 String sRange( sLNm.GetToken( 0, ::sfx2::cTokenSeperator, nPos ) );
245
246 if( pFile )
247 *pFile = sFile;
248 if( pLinkStr )
249 *pLinkStr = sRange;
250 if( pFilter )
251 *pFilter = sLNm.Copy( nPos );
252
253 if( pType )
254 {
255 sal_uInt16 nObjType = pLink->GetObjType();
256 *pType = String( SfxResId(
257 ( OBJECT_CLIENT_FILE == nObjType || OBJECT_CLIENT_OLE == nObjType )
258 ? RID_SVXSTR_FILELINK
259 : RID_SVXSTR_GRAFIKLINK ));
260 }
261 bRet = sal_True;
262 }
263 break;
264 case OBJECT_CLIENT_DDE:
265 {
266 sal_uInt16 nTmp = 0;
267 String sCmd( sLNm );
268 String sServer( sCmd.GetToken( 0, cTokenSeperator, nTmp ) );
269 String sTopic( sCmd.GetToken( 0, cTokenSeperator, nTmp ) );
270
271 if( pType )
272 *pType = sServer;
273 if( pFile )
274 *pFile = sTopic;
275 if( pLinkStr )
276 *pLinkStr = sCmd.Copy( nTmp );
277 bRet = sal_True;
278 }
279 break;
280 default:
281 break;
282 }
283 }
284
285 return bRet;
286 }
287
SetAutoAskUpdateAllLinks()288 void LinkManager::SetAutoAskUpdateAllLinks()
289 {
290 mAutoAskUpdateAllLinks = sal_True;
291 mUpdateAsked = sal_False;
292 }
293
SetNeverAskUpdateAllLinks()294 void LinkManager::SetNeverAskUpdateAllLinks()
295 {
296 mAutoAskUpdateAllLinks = sal_False;
297 mAllowUpdate = sal_True;
298 mUpdateAsked = sal_True;
299 }
300
GetUserAllowsLinkUpdate(Window * pParentWin)301 sal_Bool LinkManager::GetUserAllowsLinkUpdate(Window *pParentWin)
302 {
303 if (!mUpdateAsked)
304 {
305 if (QueryBox(pParentWin, WB_YES_NO | WB_DEF_NO, SfxResId(STR_QUERY_UPDATE_LINKS)).Execute() == RET_YES)
306 mAllowUpdate = sal_True;
307 else
308 mAllowUpdate = sal_False;
309 mUpdateAsked = sal_True;
310 }
311 return mAllowUpdate;
312 }
313
SetUserAllowsLinkUpdate(SvBaseLink * pLink,sal_Bool allows)314 void LinkManager::SetUserAllowsLinkUpdate(SvBaseLink *pLink, sal_Bool allows)
315 {
316 SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
317
318 if (pShell)
319 {
320 comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = pShell->getEmbeddedObjectContainer();
321 rEmbeddedObjectContainer.setUserAllowsLinkUpdate(allows);
322 }
323 }
324
325
UpdateAllLinks(sal_Bool bAskUpdate,sal_Bool,sal_Bool bUpdateGrfLinks,Window * pParentWin)326 void LinkManager::UpdateAllLinks(
327 sal_Bool bAskUpdate,
328 sal_Bool /*bCallErrHdl*/,
329 sal_Bool bUpdateGrfLinks,
330 Window* pParentWin )
331 {
332 SvStringsDtor aApps, aTopics, aItems;
333 String sApp, sTopic, sItem;
334
335 // first create a copy of the array, so that updated links to not interfere with ... in between!!
336 SvPtrarr aTmpArr( 255, 50 );
337 sal_uInt16 n;
338 for( n = 0; n < aLinkTbl.Count(); ++n )
339 {
340 SvBaseLink* pLink = *aLinkTbl[ n ];
341 if( !pLink )
342 {
343 Remove( n-- );
344 continue;
345 }
346 aTmpArr.Insert( pLink, aTmpArr.Count() );
347 }
348
349 for( n = 0; n < aTmpArr.Count(); ++n )
350 {
351 SvBaseLink* pLink = (SvBaseLink*)aTmpArr[ n ];
352
353 // first search the entry in the array
354 sal_uInt16 nFndPos = USHRT_MAX;
355 for( sal_uInt16 i = 0; i < aLinkTbl.Count(); ++i )
356 if( pLink == *aLinkTbl[ i ] )
357 {
358 nFndPos = i;
359 break;
360 }
361
362 if( USHRT_MAX == nFndPos )
363 continue; // was not already existing!
364
365 // do not update graphic links yet
366 if( !pLink->IsVisible() ||
367 ( !bUpdateGrfLinks && OBJECT_CLIENT_GRF == pLink->GetObjType() ))
368 continue;
369
370 sal_Bool allows = sal_True;
371
372 if (bAskUpdate)
373 {
374 allows = GetUserAllowsLinkUpdate(pParentWin);
375 }
376
377 SetUserAllowsLinkUpdate(pLink, allows);
378 bAskUpdate = sal_False; // one time is OK
379
380 if (allows)
381 pLink->Update();
382 }
383 }
384
385 /************************************************************************
386 |* SvBaseLink::CreateObject()
387 |*
388 |* Description
389 *************************************************************************/
390
CreateObj(SvBaseLink * pLink)391 SvLinkSourceRef LinkManager::CreateObj( SvBaseLink * pLink )
392 {
393 switch( pLink->GetObjType() )
394 {
395 case OBJECT_CLIENT_FILE:
396 case OBJECT_CLIENT_GRF:
397 case OBJECT_CLIENT_OLE:
398 return new SvFileObject;
399 case OBJECT_INTERN:
400 return new SvxInternalLink;
401 case OBJECT_CLIENT_DDE:
402 return new SvDDEObject;
403 default:
404 return SvLinkSourceRef();
405 }
406 }
407
InsertServer(SvLinkSource * pObj)408 sal_Bool LinkManager::InsertServer( SvLinkSource* pObj )
409 {
410 // do not insert double
411 if( !pObj || USHRT_MAX != aServerTbl.GetPos( pObj ) )
412 return sal_False;
413
414 aServerTbl.Insert( pObj, aServerTbl.Count() );
415 return sal_True;
416 }
417
418
RemoveServer(SvLinkSource * pObj)419 void LinkManager::RemoveServer( SvLinkSource* pObj )
420 {
421 sal_uInt16 nPos = aServerTbl.GetPos( pObj );
422 if( USHRT_MAX != nPos )
423 aServerTbl.Remove( nPos, 1 );
424 }
425
426
MakeLnkName(String & rName,const String * pType,const String & rFile,const String & rLink,const String * pFilter)427 void MakeLnkName( String& rName, const String* pType, const String& rFile,
428 const String& rLink, const String* pFilter )
429 {
430 if( pType )
431 (rName = *pType).EraseLeadingChars().EraseTrailingChars() += cTokenSeperator;
432 else if( rName.Len() )
433 rName.Erase();
434
435 ((rName += rFile).EraseLeadingChars().EraseTrailingChars() +=
436 cTokenSeperator ).EraseLeadingChars().EraseTrailingChars() += rLink;
437 if( pFilter )
438 ((rName += cTokenSeperator ) += *pFilter).EraseLeadingChars().EraseTrailingChars();
439 }
440
InsertFileLink(sfx2::SvBaseLink & rLink,sal_uInt16 nFileType,const String & rFileNm,const String * pFilterNm,const String * pRange)441 sal_Bool LinkManager::InsertFileLink( sfx2::SvBaseLink& rLink,
442 sal_uInt16 nFileType,
443 const String& rFileNm,
444 const String* pFilterNm,
445 const String* pRange )
446 {
447 if( !( OBJECT_CLIENT_SO & rLink.GetObjType() ))
448 return sal_False;
449
450 String sCmd( rFileNm );
451 sCmd += ::sfx2::cTokenSeperator;
452 if( pRange )
453 sCmd += *pRange;
454 if( pFilterNm )
455 ( sCmd += ::sfx2::cTokenSeperator ) += *pFilterNm;
456
457 return InsertLink( &rLink, nFileType, sfx2::LINKUPDATE_ONCALL, &sCmd );
458 }
459
InsertFileLink(sfx2::SvBaseLink & rLink)460 sal_Bool LinkManager::InsertFileLink( sfx2::SvBaseLink& rLink )
461 {
462 if( OBJECT_CLIENT_FILE == ( OBJECT_CLIENT_FILE & rLink.GetObjType() ))
463 return InsertLink( &rLink, rLink.GetObjType(), sfx2::LINKUPDATE_ONCALL );
464 return sal_False;
465 }
466
467 // a transfer will be discontinued, therefore cancel all DownloadMedia
468 // (at the moment only interesting for the FileLinks!)
CancelTransfers()469 void LinkManager::CancelTransfers()
470 {
471 SvFileObject* pFileObj;
472 sfx2::SvBaseLink* pLnk;
473
474 const sfx2::SvBaseLinks& rLnks = GetLinks();
475 for( sal_uInt16 n = rLnks.Count(); n; )
476 if( 0 != ( pLnk = &(*rLnks[ --n ])) &&
477 OBJECT_CLIENT_FILE == (OBJECT_CLIENT_FILE & pLnk->GetObjType()) &&
478 0 != ( pFileObj = (SvFileObject*)pLnk->GetObj() ) )
479 // 0 != ( pFileObj = (SvFileObject*)SvFileObject::ClassFactory()->
480 // CastAndAddRef( pLnk->GetObj() )) )
481 pFileObj->CancelTransfers();
482 }
483
484 // to send status information from the FileObject to the BaseLink, there is an own ClipboardId.
485 // The SvData object has then the respective information as string.
486 // Currently this will be used for FileObject in connection with JavaScript
487 // - that needs information about Load/Abort/Error
RegisterStatusInfoId()488 sal_uIntPtr LinkManager::RegisterStatusInfoId()
489 {
490 static sal_uIntPtr nFormat = 0;
491
492 if( !nFormat )
493 {
494 // how does the new interface look like?
495 // nFormat = Exchange::RegisterFormatName( "StatusInfo vom SvxInternalLink" );
496 nFormat = SotExchange::RegisterFormatName(
497 String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM(
498 "StatusInfo vom SvxInternalLink" )));
499 }
500 return nFormat;
501 }
502
503 // ----------------------------------------------------------------------
504
GetGraphicFromAny(const String & rMimeType,const::com::sun::star::uno::Any & rValue,Graphic & rGrf)505 sal_Bool LinkManager::GetGraphicFromAny( const String& rMimeType,
506 const ::com::sun::star::uno::Any & rValue,
507 Graphic& rGrf )
508 {
509 sal_Bool bRet = sal_False;
510 ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
511 if( rValue.hasValue() && ( rValue >>= aSeq ) )
512 {
513 SvMemoryStream aMemStm( (void*)aSeq.getConstArray(), aSeq.getLength(),
514 STREAM_READ );
515 aMemStm.Seek( 0 );
516
517 switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
518 {
519 case SOT_FORMATSTR_ID_SVXB:
520 {
521 aMemStm >> rGrf;
522 bRet = sal_True;
523 }
524 break;
525 case FORMAT_GDIMETAFILE:
526 {
527 GDIMetaFile aMtf;
528 aMtf.Read( aMemStm );
529 rGrf = aMtf;
530 bRet = sal_True;
531 }
532 break;
533 case FORMAT_BITMAP:
534 {
535 Bitmap aBmp;
536 ReadDIB(aBmp, aMemStm, true);
537 rGrf = aBmp;
538 bRet = sal_True;
539 }
540 break;
541 }
542 }
543 return bRet;
544 }
545
urlIsSafe(const::rtl::OUString & url)546 sal_Bool LinkManager::urlIsSafe( const ::rtl::OUString &url )
547 {
548 if ( url.getLength() == 0 ) {
549 return sal_False;
550 }
551 if ( !xURLTransformer.is() ) {
552 const com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > xContext ( ::comphelper::getProcessComponentContext() );
553 com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiComponentFactory > xFactory ( xContext->getServiceManager(), ::com::sun::star::uno::UNO_QUERY );
554 if ( !xFactory.is() ) {
555 return sal_False;
556 }
557 xURLTransformer.set( xFactory->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.util.URLTransformer" ), xContext), com::sun::star::uno::UNO_QUERY );
558 if ( !xURLTransformer.is() ) {
559 return sal_False;
560 }
561 }
562 com::sun::star::util::URL aURL;
563 aURL.Complete = url;
564 sal_Bool b = xURLTransformer->parseSmart( aURL, ::rtl::OUString() );
565 if ( !b ) {
566 return sal_False;
567 }
568 return urlIsSafe( aURL );
569 }
570
urlIsSafe(const::com::sun::star::util::URL & url)571 sal_Bool LinkManager::urlIsSafe( const ::com::sun::star::util::URL &url )
572 {
573 sal_Bool result = ( url.Path.getLength() == 0 ) &&
574 ( url.Server.getLength() == 0);
575 return result;
576 }
577
578
urlIsVendor(const::rtl::OUString & url)579 sal_Bool LinkManager::urlIsVendor( const ::rtl::OUString &url )
580 {
581 // One definition of this scheme set, shared with the modules below sfx2
582 // that also have to apply it (see svtools/linkpolicy.hxx).
583 return ::svt::linkpolicy::isVendorUrl( url ) ? sal_True : sal_False;
584 }
585
586
587 // ----------------------------------------------------------------------
lcl_DDE_RelToAbs(const String & rTopic,const String & rBaseURL)588 String lcl_DDE_RelToAbs( const String& rTopic, const String& rBaseURL )
589 {
590 String sRet;
591 INetURLObject aURL( rTopic );
592 if( INET_PROT_NOT_VALID == aURL.GetProtocol() )
593 utl::LocalFileHelper::ConvertSystemPathToURL( rTopic, rBaseURL, sRet );
594 if( !sRet.Len() )
595 sRet = URIHelper::SmartRel2Abs( INetURLObject(rBaseURL), rTopic, URIHelper::GetMaybeFileHdl(), true );
596 return sRet;
597 }
598
Connect(sfx2::SvBaseLink * pLink)599 sal_Bool SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
600 {
601 SfxObjectShell* pFndShell = 0;
602 sal_uInt16 nUpdateMode = com::sun::star::document::UpdateDocMode::NO_UPDATE;
603 String sTopic, sItem, sReferer;
604 if( pLink->GetLinkManager() &&
605 pLink->GetLinkManager()->GetDisplayNames( pLink, 0, &sTopic, &sItem )
606 && sTopic.Len() )
607 {
608 // for the moment run through the DocumentShells and search for the ones with names:
609
610 com::sun::star::lang::Locale aLocale;
611 MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aLocale );
612 CharClass aCC( aLocale );
613
614 String sNm( sTopic ), sTmp;
615 aCC.toLower( sNm );
616
617 TypeId aType( TYPE(SfxObjectShell) );
618
619 sal_Bool bFirst = sal_True;
620 SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
621 if( pShell && pShell->GetMedium() )
622 {
623 sReferer = pShell->GetMedium()->GetBaseURL();
624 SFX_ITEMSET_ARG( pShell->GetMedium()->GetItemSet(), pItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False );
625 if ( pItem )
626 nUpdateMode = pItem->GetValue();
627 }
628
629 String sNmURL( lcl_DDE_RelToAbs( sTopic, sReferer ) );
630 aCC.toLower( sNmURL );
631
632 if ( !pShell )
633 {
634 bFirst = sal_False;
635 pShell = SfxObjectShell::GetFirst( &aType, sal_False );
636 }
637
638 while( pShell )
639 {
640 if( !sTmp.Len() )
641 {
642 sTmp = pShell->GetTitle( SFX_TITLE_FULLNAME );
643 sTmp = lcl_DDE_RelToAbs(sTmp, sReferer );
644 }
645
646
647 aCC.toLower( sTmp );
648 if( sTmp == sNmURL ) // these we want to have
649 {
650 pFndShell = pShell;
651 break;
652 }
653
654 if( bFirst )
655 {
656 bFirst = sal_False;
657 pShell = SfxObjectShell::GetFirst( &aType, sal_False );
658 }
659 else
660 pShell = SfxObjectShell::GetNext( *pShell, &aType, sal_False );
661
662 sTmp.Erase();
663 }
664 }
665
666 // empty topics are not allowed - which document is it
667 if( !sTopic.Len() )
668 return sal_False;
669
670 if( !pFndShell )
671 {
672 // try to load the file:
673 INetURLObject aURL( sTopic );
674 INetProtocol eOld = aURL.GetProtocol();
675 aURL.SetURL( sTopic = lcl_DDE_RelToAbs( sTopic, sReferer ) );
676 if( INET_PROT_NOT_VALID != eOld ||
677 INET_PROT_HTTP != aURL.GetProtocol() )
678 {
679 SfxStringItem aName( SID_FILE_NAME, sTopic );
680 SfxBoolItem aMinimized(SID_MINIMIZED, sal_True);
681 SfxBoolItem aHidden(SID_HIDDEN, sal_True);
682 SfxStringItem aTarget( SID_TARGETNAME, String::CreateFromAscii("_blank") );
683 SfxStringItem aReferer( SID_REFERER, sReferer );
684 SfxUInt16Item aUpdate( SID_UPDATEDOCMODE, nUpdateMode );
685 SfxBoolItem aReadOnly(SID_DOC_READONLY, sal_True);
686
687 // #i14200# (DDE-link crashes wordprocessor)
688 SfxAllItemSet aArgs( SFX_APP()->GetPool() );
689 aArgs.Put(aReferer);
690 aArgs.Put(aTarget);
691 aArgs.Put(aHidden);
692 aArgs.Put(aMinimized);
693 aArgs.Put(aName);
694 aArgs.Put(aUpdate);
695 aArgs.Put(aReadOnly);
696 pFndShell = SfxObjectShell::CreateAndLoadObject( aArgs );
697 }
698 }
699
700 sal_Bool bRet = sal_False;
701 if( pFndShell )
702 {
703 sfx2::SvLinkSource* pNewSrc = pFndShell->DdeCreateLinkSource( sItem );
704 if( pNewSrc )
705 {
706 bRet = sal_True;
707
708 ::com::sun::star::datatransfer::DataFlavor aFl;
709 SotExchange::GetFormatDataFlavor( pLink->GetContentType(), aFl );
710
711 pLink->SetObj( pNewSrc );
712 pNewSrc->AddDataAdvise( pLink, aFl.MimeType,
713 sfx2::LINKUPDATE_ONCALL == pLink->GetUpdateMode()
714 ? ADVISEMODE_ONLYONCE
715 : 0 );
716 }
717 }
718 return bRet;
719 }
720
721
722 }
723