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