xref: /AOO41X/main/sfx2/source/appl/linkmgr2.cxx (revision 83137a03adbb58b5b3bdafefefa1e93de35e0011)
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     mUpdateAsked(sal_False),
70     mAutoAskUpdateAllLinks(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 |*    Beschreibung
93 *************************************************************************/
94 
95 void LinkManager::Remove( SvBaseLink *pLink )
96 {
97     // keine Links doppelt einfuegen
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         // falls noch leere rum stehen sollten, weg damit
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     // keine Links doppelt einfuegen
148     for( sal_uInt16 n = 0; n < aLinkTbl.Count(); ++n )
149     {
150         SvBaseLinkRef* pTmp = aLinkTbl[ n ];
151         if( !pTmp->Is() )
152             aLinkTbl.DeleteAndDestroy( n-- );
153 
154         if( pLink == *pTmp )
155             return sal_False;
156     }
157 
158     SvBaseLinkRef* pTmp = new SvBaseLinkRef( pLink );
159     pLink->SetLinkManager( this );
160     aLinkTbl.Insert( pTmp, aLinkTbl.Count() );
161     if (mAutoAskUpdateAllLinks)
162     {
163         Window *parent = NULL;
164         SfxObjectShell* persist = GetPersist();
165         if (persist != NULL)
166             parent = GetPersist()->GetDialogParent();
167 
168         SetUserAllowsLinkUpdate(pLink, GetUserAllowsLinkUpdate(parent));
169     }
170 
171     return sal_True;
172 }
173 
174 
175 sal_Bool LinkManager::InsertLink( SvBaseLink * pLink,
176                                 sal_uInt16 nObjType,
177                                 sal_uInt16 nUpdateMode,
178                                 const String* pName )
179 {
180     // unbedingt zuerst
181     pLink->SetObjType( nObjType );
182     if( pName )
183         pLink->SetName( *pName );
184     pLink->SetUpdateMode( nUpdateMode );
185     return Insert( pLink );
186 }
187 
188 
189 sal_Bool LinkManager::InsertDDELink( SvBaseLink * pLink,
190                                     const String& rServer,
191                                     const String& rTopic,
192                                     const String& rItem )
193 {
194     if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
195         return sal_False;
196 
197     String sCmd;
198     ::sfx2::MakeLnkName( sCmd, &rServer, rTopic, rItem );
199 
200     pLink->SetObjType( OBJECT_CLIENT_DDE );
201     pLink->SetName( sCmd );
202     return Insert( pLink );
203 }
204 
205 
206 sal_Bool LinkManager::InsertDDELink( SvBaseLink * pLink )
207 {
208     DBG_ASSERT( OBJECT_CLIENT_SO & pLink->GetObjType(), "no OBJECT_CLIENT_SO" );
209     if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
210         return sal_False;
211 
212     if( pLink->GetObjType() == OBJECT_CLIENT_SO )
213         pLink->SetObjType( OBJECT_CLIENT_DDE );
214 
215     return Insert( pLink );
216 }
217 
218 
219 // erfrage die Strings fuer den Dialog
220 sal_Bool LinkManager::GetDisplayNames( const SvBaseLink * pLink,
221                                         String* pType,
222                                         String* pFile,
223                                         String* pLinkStr,
224                                         String* pFilter ) const
225 {
226     sal_Bool bRet = sal_False;
227     const String sLNm( pLink->GetLinkSourceName() );
228     if( sLNm.Len() )
229     {
230         switch( pLink->GetObjType() )
231         {
232             case OBJECT_CLIENT_FILE:
233             case OBJECT_CLIENT_GRF:
234             case OBJECT_CLIENT_OLE:
235                 {
236                     sal_uInt16 nPos = 0;
237                     String sFile( sLNm.GetToken( 0, ::sfx2::cTokenSeperator, nPos ) );
238                     String sRange( sLNm.GetToken( 0, ::sfx2::cTokenSeperator, nPos ) );
239 
240                     if( pFile )
241                         *pFile = sFile;
242                     if( pLinkStr )
243                         *pLinkStr = sRange;
244                     if( pFilter )
245                         *pFilter = sLNm.Copy( nPos );
246 
247                     if( pType )
248                     {
249                         sal_uInt16 nObjType = pLink->GetObjType();
250                         *pType = String( SfxResId(
251                                     ( OBJECT_CLIENT_FILE == nObjType || OBJECT_CLIENT_OLE == nObjType )
252                                             ? RID_SVXSTR_FILELINK
253                                             : RID_SVXSTR_GRAFIKLINK ));
254                     }
255                     bRet = sal_True;
256                 }
257                 break;
258             case OBJECT_CLIENT_DDE:
259                 {
260                     sal_uInt16 nTmp = 0;
261                     String sCmd( sLNm );
262                     String sServer( sCmd.GetToken( 0, cTokenSeperator, nTmp ) );
263                     String sTopic( sCmd.GetToken( 0, cTokenSeperator, nTmp ) );
264 
265                     if( pType )
266                         *pType = sServer;
267                     if( pFile )
268                         *pFile = sTopic;
269                     if( pLinkStr )
270                         *pLinkStr = sCmd.Copy( nTmp );
271                     bRet = sal_True;
272                 }
273                 break;
274             default:
275                 break;
276         }
277     }
278 
279     return bRet;
280 }
281 
282 void LinkManager::SetAutoAskUpdateAllLinks()
283 {
284     mAutoAskUpdateAllLinks = sal_True;
285 }
286 
287 sal_Bool LinkManager::GetUserAllowsLinkUpdate(Window *pParentWin)
288 {
289     if (!mUpdateAsked)
290     {
291         if (QueryBox(pParentWin, WB_YES_NO | WB_DEF_NO, SfxResId(STR_QUERY_UPDATE_LINKS)).Execute() == RET_YES)
292             mAllowUpdate = sal_True;
293         else
294             mAllowUpdate = sal_False;
295         mUpdateAsked = sal_True;
296     }
297     return mAllowUpdate;
298 }
299 
300 void LinkManager::SetUserAllowsLinkUpdate(SvBaseLink *pLink, sal_Bool allows)
301 {
302     SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
303 
304     if (pShell)
305     {
306         comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = pShell->getEmbeddedObjectContainer();
307         rEmbeddedObjectContainer.setUserAllowsLinkUpdate(allows);
308     }
309 }
310 
311 
312 void LinkManager::UpdateAllLinks(
313     sal_Bool bAskUpdate,
314     sal_Bool /*bCallErrHdl*/,
315     sal_Bool bUpdateGrfLinks,
316     Window* pParentWin )
317 {
318     SvStringsDtor aApps, aTopics, aItems;
319     String sApp, sTopic, sItem;
320 
321     // erstmal eine Kopie vom Array machen, damit sich updatende Links in
322     // Links in ... nicht dazwischen funken!!
323     SvPtrarr aTmpArr( 255, 50 );
324     sal_uInt16 n;
325     for( n = 0; n < aLinkTbl.Count(); ++n )
326     {
327         SvBaseLink* pLink = *aLinkTbl[ n ];
328         if( !pLink )
329         {
330             Remove( n-- );
331             continue;
332         }
333         aTmpArr.Insert( pLink, aTmpArr.Count() );
334     }
335 
336     for( n = 0; n < aTmpArr.Count(); ++n )
337     {
338         SvBaseLink* pLink = (SvBaseLink*)aTmpArr[ n ];
339 
340         // suche erstmal im Array nach dem Eintrag
341         sal_uInt16 nFndPos = USHRT_MAX;
342         for( sal_uInt16 i = 0; i < aLinkTbl.Count(); ++i )
343             if( pLink == *aLinkTbl[ i ] )
344             {
345                 nFndPos = i;
346                 break;
347             }
348 
349         if( USHRT_MAX == nFndPos )
350             continue;                   // war noch nicht vorhanden!
351 
352         // do not update graphic links yet
353         if( !pLink->IsVisible() ||
354             ( !bUpdateGrfLinks && OBJECT_CLIENT_GRF == pLink->GetObjType() ))
355             continue;
356 
357         sal_Bool allows = sal_True;
358 
359         if (bAskUpdate)
360         {
361             allows = GetUserAllowsLinkUpdate(pParentWin);
362         }
363 
364         SetUserAllowsLinkUpdate(pLink, allows);
365         bAskUpdate = sal_False;     // one time is OK
366 
367         if (allows)
368             pLink->Update();
369 
370     }
371 }
372 
373 /************************************************************************
374 |*    SvBaseLink::CreateObject()
375 |*
376 |*    Beschreibung
377 *************************************************************************/
378 
379 SvLinkSourceRef LinkManager::CreateObj( SvBaseLink * pLink )
380 {
381     switch( pLink->GetObjType() )
382     {
383         case OBJECT_CLIENT_FILE:
384         case OBJECT_CLIENT_GRF:
385         case OBJECT_CLIENT_OLE:
386             return new SvFileObject;
387         case OBJECT_INTERN:
388             return new SvxInternalLink;
389         case OBJECT_CLIENT_DDE:
390             return new SvDDEObject;
391         default:
392             return SvLinkSourceRef();
393     }
394 }
395 
396 sal_Bool LinkManager::InsertServer( SvLinkSource* pObj )
397 {
398     // keine doppelt einfuegen
399     if( !pObj || USHRT_MAX != aServerTbl.GetPos( pObj ) )
400         return sal_False;
401 
402     aServerTbl.Insert( pObj, aServerTbl.Count() );
403     return sal_True;
404 }
405 
406 
407 void LinkManager::RemoveServer( SvLinkSource* pObj )
408 {
409     sal_uInt16 nPos = aServerTbl.GetPos( pObj );
410     if( USHRT_MAX != nPos )
411         aServerTbl.Remove( nPos, 1 );
412 }
413 
414 
415 void MakeLnkName( String& rName, const String* pType, const String& rFile,
416                     const String& rLink, const String* pFilter )
417 {
418     if( pType )
419         (rName = *pType).EraseLeadingChars().EraseTrailingChars() += cTokenSeperator;
420     else if( rName.Len() )
421         rName.Erase();
422 
423     ((rName += rFile).EraseLeadingChars().EraseTrailingChars() +=
424         cTokenSeperator ).EraseLeadingChars().EraseTrailingChars() += rLink;
425     if( pFilter )
426         ((rName += cTokenSeperator ) += *pFilter).EraseLeadingChars().EraseTrailingChars();
427 }
428 
429 sal_Bool LinkManager::InsertFileLink( sfx2::SvBaseLink& rLink,
430                                     sal_uInt16 nFileType,
431                                     const String& rFileNm,
432                                     const String* pFilterNm,
433                                     const String* pRange )
434 {
435     if( !( OBJECT_CLIENT_SO & rLink.GetObjType() ))
436         return sal_False;
437 
438     String sCmd( rFileNm );
439     sCmd += ::sfx2::cTokenSeperator;
440     if( pRange )
441         sCmd += *pRange;
442     if( pFilterNm )
443         ( sCmd += ::sfx2::cTokenSeperator ) += *pFilterNm;
444 
445     return InsertLink( &rLink, nFileType, sfx2::LINKUPDATE_ONCALL, &sCmd );
446 }
447 
448 sal_Bool LinkManager::InsertFileLink( sfx2::SvBaseLink& rLink )
449 {
450     if( OBJECT_CLIENT_FILE == ( OBJECT_CLIENT_FILE & rLink.GetObjType() ))
451         return InsertLink( &rLink, rLink.GetObjType(), sfx2::LINKUPDATE_ONCALL );
452     return sal_False;
453 }
454 
455 // eine Uebertragung wird abgebrochen, also alle DownloadMedien canceln
456 // (ist zur Zeit nur fuer die FileLinks interressant!)
457 void LinkManager::CancelTransfers()
458 {
459     SvFileObject* pFileObj;
460     sfx2::SvBaseLink* pLnk;
461 
462     const sfx2::SvBaseLinks& rLnks = GetLinks();
463     for( sal_uInt16 n = rLnks.Count(); n; )
464         if( 0 != ( pLnk = &(*rLnks[ --n ])) &&
465             OBJECT_CLIENT_FILE == (OBJECT_CLIENT_FILE & pLnk->GetObjType()) &&
466             0 != ( pFileObj = (SvFileObject*)pLnk->GetObj() ) )
467 //          0 != ( pFileObj = (SvFileObject*)SvFileObject::ClassFactory()->
468 //                                  CastAndAddRef( pLnk->GetObj() )) )
469             pFileObj->CancelTransfers();
470 }
471 
472     // um Status Informationen aus dem FileObject an den BaseLink zu
473     // senden, gibt es eine eigene ClipBoardId. Das SvData-Object hat
474     // dann die entsprechenden Informationen als String.
475     // Wird zur Zeit fuer FileObject in Verbindung mit JavaScript benoetigt
476     // - das braucht Informationen ueber Load/Abort/Error
477 sal_uIntPtr LinkManager::RegisterStatusInfoId()
478 {
479     static sal_uIntPtr nFormat = 0;
480 
481     if( !nFormat )
482     {
483 // wie sieht die neue Schnittstelle aus?
484 //      nFormat = Exchange::RegisterFormatName( "StatusInfo vom SvxInternalLink" );
485         nFormat = SotExchange::RegisterFormatName(
486                     String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM(
487                                 "StatusInfo vom SvxInternalLink" )));
488     }
489     return nFormat;
490 }
491 
492 // ----------------------------------------------------------------------
493 
494 sal_Bool LinkManager::GetGraphicFromAny( const String& rMimeType,
495                                 const ::com::sun::star::uno::Any & rValue,
496                                 Graphic& rGrf )
497 {
498     sal_Bool bRet = sal_False;
499     ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
500     if( rValue.hasValue() && ( rValue >>= aSeq ) )
501     {
502         SvMemoryStream aMemStm( (void*)aSeq.getConstArray(), aSeq.getLength(),
503                                 STREAM_READ );
504         aMemStm.Seek( 0 );
505 
506         switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
507         {
508         case SOT_FORMATSTR_ID_SVXB:
509             {
510                 aMemStm >> rGrf;
511                 bRet = sal_True;
512             }
513             break;
514         case FORMAT_GDIMETAFILE:
515             {
516                 GDIMetaFile aMtf;
517                 aMtf.Read( aMemStm );
518                 rGrf = aMtf;
519                 bRet = sal_True;
520             }
521             break;
522         case FORMAT_BITMAP:
523             {
524                 Bitmap aBmp;
525                 ReadDIB(aBmp, aMemStm, true);
526                 rGrf = aBmp;
527                 bRet = sal_True;
528             }
529             break;
530         }
531     }
532     return bRet;
533 }
534 
535 
536 // ----------------------------------------------------------------------
537 String lcl_DDE_RelToAbs( const String& rTopic, const String& rBaseURL )
538 {
539     String sRet;
540     INetURLObject aURL( rTopic );
541     if( INET_PROT_NOT_VALID == aURL.GetProtocol() )
542         utl::LocalFileHelper::ConvertSystemPathToURL( rTopic, rBaseURL, sRet );
543     if( !sRet.Len() )
544         sRet = URIHelper::SmartRel2Abs( INetURLObject(rBaseURL), rTopic, URIHelper::GetMaybeFileHdl(), true );
545     return sRet;
546 }
547 
548 sal_Bool SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
549 {
550     SfxObjectShell* pFndShell = 0;
551     sal_uInt16 nUpdateMode = com::sun::star::document::UpdateDocMode::NO_UPDATE;
552     String sTopic, sItem, sReferer;
553     if( pLink->GetLinkManager() &&
554         pLink->GetLinkManager()->GetDisplayNames( pLink, 0, &sTopic, &sItem )
555         && sTopic.Len() )
556     {
557         // erstmal nur ueber die DocumentShells laufen und die mit dem
558         // Namen heraussuchen:
559 
560         com::sun::star::lang::Locale aLocale;
561         MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aLocale );
562         CharClass aCC( aLocale );
563 
564         String sNm( sTopic ), sTmp;
565         aCC.toLower( sNm );
566 
567         TypeId aType( TYPE(SfxObjectShell) );
568 
569         sal_Bool bFirst = sal_True;
570         SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
571         if( pShell && pShell->GetMedium() )
572         {
573             sReferer = pShell->GetMedium()->GetBaseURL();
574             SFX_ITEMSET_ARG( pShell->GetMedium()->GetItemSet(), pItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False );
575             if ( pItem )
576                 nUpdateMode = pItem->GetValue();
577         }
578 
579         String sNmURL( lcl_DDE_RelToAbs( sTopic, sReferer ) );
580         aCC.toLower( sNmURL );
581 
582         if ( !pShell )
583         {
584             bFirst = sal_False;
585             pShell = SfxObjectShell::GetFirst( &aType, sal_False );
586         }
587 
588         while( pShell )
589         {
590             if( !sTmp.Len() )
591             {
592                 sTmp = pShell->GetTitle( SFX_TITLE_FULLNAME );
593                 sTmp = lcl_DDE_RelToAbs(sTmp, sReferer );
594             }
595 
596 
597             aCC.toLower( sTmp );
598             if( sTmp == sNmURL )        // die wollen wir haben
599             {
600                 pFndShell = pShell;
601                 break;
602             }
603 
604             if( bFirst )
605             {
606                 bFirst = sal_False;
607                 pShell = SfxObjectShell::GetFirst( &aType, sal_False );
608             }
609             else
610                 pShell = SfxObjectShell::GetNext( *pShell, &aType, sal_False );
611 
612             sTmp.Erase();
613         }
614     }
615 
616     // empty topics are not allowed - which document is it
617     if( !sTopic.Len() )
618         return sal_False;
619 
620     if( !pFndShell )
621     {
622         // dann versuche die Datei zu laden:
623         INetURLObject aURL( sTopic );
624         INetProtocol eOld = aURL.GetProtocol();
625         aURL.SetURL( sTopic = lcl_DDE_RelToAbs( sTopic, sReferer ) );
626         if( INET_PROT_NOT_VALID != eOld ||
627             INET_PROT_HTTP != aURL.GetProtocol() )
628         {
629             SfxStringItem aName( SID_FILE_NAME, sTopic );
630             SfxBoolItem aMinimized(SID_MINIMIZED, sal_True);
631             SfxBoolItem aHidden(SID_HIDDEN, sal_True);
632             SfxStringItem aTarget( SID_TARGETNAME, String::CreateFromAscii("_blank") );
633             SfxStringItem aReferer( SID_REFERER, sReferer );
634             SfxUInt16Item aUpdate( SID_UPDATEDOCMODE, nUpdateMode );
635             SfxBoolItem aReadOnly(SID_DOC_READONLY, sal_True);
636 
637             // #i14200# (DDE-link crashes wordprocessor)
638             SfxAllItemSet aArgs( SFX_APP()->GetPool() );
639             aArgs.Put(aReferer);
640             aArgs.Put(aTarget);
641             aArgs.Put(aHidden);
642             aArgs.Put(aMinimized);
643             aArgs.Put(aName);
644             aArgs.Put(aUpdate);
645             aArgs.Put(aReadOnly);
646             pFndShell = SfxObjectShell::CreateAndLoadObject( aArgs );
647         }
648     }
649 
650     sal_Bool bRet = sal_False;
651     if( pFndShell )
652     {
653         sfx2::SvLinkSource* pNewSrc = pFndShell->DdeCreateLinkSource( sItem );
654         if( pNewSrc )
655         {
656             bRet = sal_True;
657 
658             ::com::sun::star::datatransfer::DataFlavor aFl;
659             SotExchange::GetFormatDataFlavor( pLink->GetContentType(), aFl );
660 
661             pLink->SetObj( pNewSrc );
662             pNewSrc->AddDataAdvise( pLink, aFl.MimeType,
663                                 sfx2::LINKUPDATE_ONCALL == pLink->GetUpdateMode()
664                                     ? ADVISEMODE_ONLYONCE
665                                     : 0 );
666         }
667     }
668     return bRet;
669 }
670 
671 
672 }
673 
674 
675 
676