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