xref: /AOO41X/main/sfx2/source/appl/linkmgr2.cxx (revision e1390266ac3390ed01f5e7bc5d6890c477f08573)
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 <comphelper/processfactory.hxx>
45 #include <i18npool/mslangid.hxx>
46 #include <sfx2/request.hxx>
47 #include <vcl/dibtools.hxx>
48 
49 #include "fileobj.hxx"
50 #include "impldde.hxx"
51 #include "app.hrc"
52 #include "sfx2/sfxresid.hxx"
53 
54 #define _SVSTDARR_STRINGSDTOR
55 #include <svl/svstdarr.hxx>
56 
57 namespace sfx2
58 {
59 
60 class SvxInternalLink : public sfx2::SvLinkSource
61 {
62 public:
SvxInternalLink()63     SvxInternalLink() {}
64 
65     virtual sal_Bool Connect( sfx2::SvBaseLink* );
66 };
67 
68 
SV_IMPL_PTRARR(SvBaseLinks,SvBaseLinkRefPtr)69 SV_IMPL_PTRARR( SvBaseLinks, SvBaseLinkRefPtr )
70 
71 LinkManager::LinkManager(SfxObjectShell* p)
72     : pPersist(p),
73     mAutoAskUpdateAllLinks(sal_False),
74     mUpdateAsked(sal_False)
75 {
76 }
77 
~LinkManager()78 LinkManager::~LinkManager()
79 {
80     SvBaseLinkRef** ppRef = (SvBaseLinkRef**)aLinkTbl.GetData();
81     for( sal_uInt16 n = aLinkTbl.Count(); n; --n, ++ppRef )
82     {
83         if( (*ppRef)->Is() )
84         {
85             (*(*ppRef))->Disconnect();
86             (*(*ppRef))->SetLinkManager( NULL );
87         }
88         delete *ppRef;
89     }
90 }
91 
92 
93 /************************************************************************
94 |*    LinkManager::Remove()
95 |*
96 |*    Beschreibung
97 *************************************************************************/
98 
Remove(SvBaseLink * pLink)99 void LinkManager::Remove( SvBaseLink *pLink )
100 {
101     // keine Links doppelt einfuegen
102     int bFound = sal_False;
103     SvBaseLinkRef** ppRef = (SvBaseLinkRef**)aLinkTbl.GetData();
104     for( sal_uInt16 n = aLinkTbl.Count(); n; --n, ++ppRef )
105     {
106         if( pLink == *(*ppRef) )
107         {
108             (*(*ppRef))->Disconnect();
109             (*(*ppRef))->SetLinkManager( NULL );
110             (*(*ppRef)).Clear();
111             bFound = sal_True;
112         }
113 
114         // falls noch leere rum stehen sollten, weg damit
115         if( !(*ppRef)->Is() )
116         {
117             delete *ppRef;
118             aLinkTbl.Remove( aLinkTbl.Count() - n, 1 );
119             if( bFound )
120                 return ;
121             --ppRef;
122         }
123     }
124 }
125 
126 
Remove(sal_uInt16 nPos,sal_uInt16 nCnt)127 void LinkManager::Remove( sal_uInt16 nPos, sal_uInt16 nCnt )
128 {
129     if( nCnt && nPos < aLinkTbl.Count() )
130     {
131         if( nPos + nCnt > aLinkTbl.Count() )
132             nCnt = aLinkTbl.Count() - nPos;
133 
134         SvBaseLinkRef** ppRef = (SvBaseLinkRef**)aLinkTbl.GetData() + nPos;
135         for( sal_uInt16 n = nCnt; n; --n, ++ppRef )
136         {
137             if( (*ppRef)->Is() )
138             {
139                 (*(*ppRef))->Disconnect();
140                 (*(*ppRef))->SetLinkManager( NULL );
141             }
142             delete *ppRef;
143         }
144         aLinkTbl.Remove( nPos, nCnt );
145     }
146 }
147 
148 
Insert(SvBaseLink * pLink)149 sal_Bool LinkManager::Insert( SvBaseLink* pLink )
150 {
151     // keine Links doppelt einfuegen
152     for( sal_uInt16 n = 0; n < aLinkTbl.Count(); ++n )
153     {
154         SvBaseLinkRef* pTmp = aLinkTbl[ n ];
155         if( !pTmp->Is() )
156             aLinkTbl.DeleteAndDestroy( n-- );
157 
158         if( pLink == *pTmp )
159             return sal_False;
160     }
161 
162     SvBaseLinkRef* pTmp = new SvBaseLinkRef( pLink );
163     pLink->SetLinkManager( this );
164     aLinkTbl.Insert( pTmp, aLinkTbl.Count() );
165     if (mAutoAskUpdateAllLinks)
166     {
167         Window *parent = NULL;
168         SfxObjectShell* persist = GetPersist();
169         if (persist != NULL)
170             parent = GetPersist()->GetDialogParent();
171 
172         SetUserAllowsLinkUpdate(pLink, GetUserAllowsLinkUpdate(parent));
173     }
174 
175     return sal_True;
176 }
177 
178 
InsertLink(SvBaseLink * pLink,sal_uInt16 nObjType,sal_uInt16 nUpdateMode,const String * pName)179 sal_Bool LinkManager::InsertLink( SvBaseLink * pLink,
180                                 sal_uInt16 nObjType,
181                                 sal_uInt16 nUpdateMode,
182                                 const String* pName )
183 {
184     // unbedingt zuerst
185     pLink->SetObjType( nObjType );
186     if( pName )
187         pLink->SetName( *pName );
188     pLink->SetUpdateMode( nUpdateMode );
189     return Insert( pLink );
190 }
191 
192 
InsertDDELink(SvBaseLink * pLink,const String & rServer,const String & rTopic,const String & rItem)193 sal_Bool LinkManager::InsertDDELink( SvBaseLink * pLink,
194                                     const String& rServer,
195                                     const String& rTopic,
196                                     const String& rItem )
197 {
198     if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
199         return sal_False;
200 
201     String sCmd;
202     ::sfx2::MakeLnkName( sCmd, &rServer, rTopic, rItem );
203 
204     pLink->SetObjType( OBJECT_CLIENT_DDE );
205     pLink->SetName( sCmd );
206     return Insert( pLink );
207 }
208 
209 
InsertDDELink(SvBaseLink * pLink)210 sal_Bool LinkManager::InsertDDELink( SvBaseLink * pLink )
211 {
212     DBG_ASSERT( OBJECT_CLIENT_SO & pLink->GetObjType(), "no OBJECT_CLIENT_SO" );
213     if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
214         return sal_False;
215 
216     if( pLink->GetObjType() == OBJECT_CLIENT_SO )
217         pLink->SetObjType( OBJECT_CLIENT_DDE );
218 
219     return Insert( pLink );
220 }
221 
222 
223 // erfrage die Strings fuer den Dialog
GetDisplayNames(const SvBaseLink * pLink,String * pType,String * pFile,String * pLinkStr,String * pFilter) const224 sal_Bool LinkManager::GetDisplayNames( const SvBaseLink * pLink,
225                                         String* pType,
226                                         String* pFile,
227                                         String* pLinkStr,
228                                         String* pFilter ) const
229 {
230     sal_Bool bRet = sal_False;
231     const String sLNm( pLink->GetLinkSourceName() );
232     if( sLNm.Len() )
233     {
234         switch( pLink->GetObjType() )
235         {
236             case OBJECT_CLIENT_FILE:
237             case OBJECT_CLIENT_GRF:
238             case OBJECT_CLIENT_OLE:
239                 {
240                     sal_uInt16 nPos = 0;
241                     String sFile( sLNm.GetToken( 0, ::sfx2::cTokenSeperator, nPos ) );
242                     String sRange( sLNm.GetToken( 0, ::sfx2::cTokenSeperator, nPos ) );
243 
244                     if( pFile )
245                         *pFile = sFile;
246                     if( pLinkStr )
247                         *pLinkStr = sRange;
248                     if( pFilter )
249                         *pFilter = sLNm.Copy( nPos );
250 
251                     if( pType )
252                     {
253                         sal_uInt16 nObjType = pLink->GetObjType();
254                         *pType = String( SfxResId(
255                                     ( OBJECT_CLIENT_FILE == nObjType || OBJECT_CLIENT_OLE == nObjType )
256                                             ? RID_SVXSTR_FILELINK
257                                             : RID_SVXSTR_GRAFIKLINK ));
258                     }
259                     bRet = sal_True;
260                 }
261                 break;
262             case OBJECT_CLIENT_DDE:
263                 {
264                     sal_uInt16 nTmp = 0;
265                     String sCmd( sLNm );
266                     String sServer( sCmd.GetToken( 0, cTokenSeperator, nTmp ) );
267                     String sTopic( sCmd.GetToken( 0, cTokenSeperator, nTmp ) );
268 
269                     if( pType )
270                         *pType = sServer;
271                     if( pFile )
272                         *pFile = sTopic;
273                     if( pLinkStr )
274                         *pLinkStr = sCmd.Copy( nTmp );
275                     bRet = sal_True;
276                 }
277                 break;
278             default:
279                 break;
280         }
281     }
282 
283     return bRet;
284 }
285 
SetAutoAskUpdateAllLinks()286 void LinkManager::SetAutoAskUpdateAllLinks()
287 {
288     mAutoAskUpdateAllLinks = sal_True;
289     mUpdateAsked = sal_False;
290 }
291 
SetNeverAskUpdateAllLinks()292 void LinkManager::SetNeverAskUpdateAllLinks()
293 {
294     mAutoAskUpdateAllLinks = sal_False;
295     mAllowUpdate = sal_True;
296     mUpdateAsked = sal_True;
297 }
298 
GetUserAllowsLinkUpdate(Window * pParentWin)299 sal_Bool LinkManager::GetUserAllowsLinkUpdate(Window *pParentWin)
300 {
301     if (!mUpdateAsked)
302     {
303         if (QueryBox(pParentWin, WB_YES_NO | WB_DEF_NO, SfxResId(STR_QUERY_UPDATE_LINKS)).Execute() == RET_YES)
304             mAllowUpdate = sal_True;
305         else
306             mAllowUpdate = sal_False;
307         mUpdateAsked = sal_True;
308     }
309     return mAllowUpdate;
310 }
311 
SetUserAllowsLinkUpdate(SvBaseLink * pLink,sal_Bool allows)312 void LinkManager::SetUserAllowsLinkUpdate(SvBaseLink *pLink, sal_Bool allows)
313 {
314     SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
315 
316     if (pShell)
317     {
318         comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = pShell->getEmbeddedObjectContainer();
319         rEmbeddedObjectContainer.setUserAllowsLinkUpdate(allows);
320     }
321 }
322 
323 
UpdateAllLinks(sal_Bool bAskUpdate,sal_Bool,sal_Bool bUpdateGrfLinks,Window * pParentWin)324 void LinkManager::UpdateAllLinks(
325     sal_Bool bAskUpdate,
326     sal_Bool /*bCallErrHdl*/,
327     sal_Bool bUpdateGrfLinks,
328     Window* pParentWin )
329 {
330     SvStringsDtor aApps, aTopics, aItems;
331     String sApp, sTopic, sItem;
332 
333     // erstmal eine Kopie vom Array machen, damit sich updatende Links in
334     // Links in ... nicht dazwischen funken!!
335     SvPtrarr aTmpArr( 255, 50 );
336     sal_uInt16 n;
337     for( n = 0; n < aLinkTbl.Count(); ++n )
338     {
339         SvBaseLink* pLink = *aLinkTbl[ n ];
340         if( !pLink )
341         {
342             Remove( n-- );
343             continue;
344         }
345         aTmpArr.Insert( pLink, aTmpArr.Count() );
346     }
347 
348     for( n = 0; n < aTmpArr.Count(); ++n )
349     {
350         SvBaseLink* pLink = (SvBaseLink*)aTmpArr[ n ];
351 
352         // suche erstmal im Array nach dem Eintrag
353         sal_uInt16 nFndPos = USHRT_MAX;
354         for( sal_uInt16 i = 0; i < aLinkTbl.Count(); ++i )
355             if( pLink == *aLinkTbl[ i ] )
356             {
357                 nFndPos = i;
358                 break;
359             }
360 
361         if( USHRT_MAX == nFndPos )
362             continue;                   // war noch nicht vorhanden!
363 
364         // do not update graphic links yet
365         if( !pLink->IsVisible() ||
366             ( !bUpdateGrfLinks && OBJECT_CLIENT_GRF == pLink->GetObjType() ))
367             continue;
368 
369         sal_Bool allows = sal_True;
370 
371         if (bAskUpdate)
372         {
373             allows = GetUserAllowsLinkUpdate(pParentWin);
374         }
375 
376         SetUserAllowsLinkUpdate(pLink, allows);
377         bAskUpdate = sal_False;     // one time is OK
378 
379         if (allows)
380             pLink->Update();
381 
382     }
383 }
384 
385 /************************************************************************
386 |*    SvBaseLink::CreateObject()
387 |*
388 |*    Beschreibung
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     // keine doppelt einfuegen
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 // eine Uebertragung wird abgebrochen, also alle DownloadMedien canceln
468 // (ist zur Zeit nur fuer die FileLinks interressant!)
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     // um Status Informationen aus dem FileObject an den BaseLink zu
485     // senden, gibt es eine eigene ClipBoardId. Das SvData-Object hat
486     // dann die entsprechenden Informationen als String.
487     // Wird zur Zeit fuer FileObject in Verbindung mit JavaScript benoetigt
488     // - das braucht Informationen ueber Load/Abort/Error
RegisterStatusInfoId()489 sal_uIntPtr LinkManager::RegisterStatusInfoId()
490 {
491     static sal_uIntPtr nFormat = 0;
492 
493     if( !nFormat )
494     {
495 // wie sieht die neue Schnittstelle aus?
496 //      nFormat = Exchange::RegisterFormatName( "StatusInfo vom SvxInternalLink" );
497         nFormat = SotExchange::RegisterFormatName(
498                     String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM(
499                                 "StatusInfo vom SvxInternalLink" )));
500     }
501     return nFormat;
502 }
503 
504 // ----------------------------------------------------------------------
505 
GetGraphicFromAny(const String & rMimeType,const::com::sun::star::uno::Any & rValue,Graphic & rGrf)506 sal_Bool LinkManager::GetGraphicFromAny( const String& rMimeType,
507                                 const ::com::sun::star::uno::Any & rValue,
508                                 Graphic& rGrf )
509 {
510     sal_Bool bRet = sal_False;
511     ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
512     if( rValue.hasValue() && ( rValue >>= aSeq ) )
513     {
514         SvMemoryStream aMemStm( (void*)aSeq.getConstArray(), aSeq.getLength(),
515                                 STREAM_READ );
516         aMemStm.Seek( 0 );
517 
518         switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
519         {
520         case SOT_FORMATSTR_ID_SVXB:
521             {
522                 aMemStm >> rGrf;
523                 bRet = sal_True;
524             }
525             break;
526         case FORMAT_GDIMETAFILE:
527             {
528                 GDIMetaFile aMtf;
529                 aMtf.Read( aMemStm );
530                 rGrf = aMtf;
531                 bRet = sal_True;
532             }
533             break;
534         case FORMAT_BITMAP:
535             {
536                 Bitmap aBmp;
537                 ReadDIB(aBmp, aMemStm, true);
538                 rGrf = aBmp;
539                 bRet = sal_True;
540             }
541             break;
542         }
543     }
544     return bRet;
545 }
546 
urlIsSafe(const::rtl::OUString & url)547 sal_Bool LinkManager::urlIsSafe( const ::rtl::OUString &url )
548 {
549     if ( url.getLength() == 0 ) {
550         return sal_False;
551     }
552     if ( !xURLTransformer.is() ) {
553         const com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > xContext ( ::comphelper::getProcessComponentContext() );
554         com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiComponentFactory > xFactory ( xContext->getServiceManager(), ::com::sun::star::uno::UNO_QUERY );
555         if ( !xFactory.is() ) {
556             return sal_False;
557         }
558         xURLTransformer.set( xFactory->createInstanceWithContext( rtl::OUString::createFromAscii( "com.sun.star.util.URLTransformer" ), xContext), com::sun::star::uno::UNO_QUERY );
559         if ( !xURLTransformer.is() ) {
560             return sal_False;
561         }
562     }
563     com::sun::star::util::URL aURL;
564     aURL.Complete = url;
565     sal_Bool b = xURLTransformer->parseSmart( aURL, ::rtl::OUString() );
566     if ( !b ) {
567         return sal_False;
568     }
569     return urlIsSafe( aURL );
570 }
571 
urlIsSafe(const::com::sun::star::util::URL & url)572 sal_Bool LinkManager::urlIsSafe( const ::com::sun::star::util::URL &url )
573 {
574     sal_Bool result = ( url.Path.getLength() == 0 ) &&
575         ( url.Server.getLength() == 0);
576     return result;
577 }
578 
579 
urlIsVendor(const::rtl::OUString & url)580 sal_Bool LinkManager::urlIsVendor( const ::rtl::OUString &url )
581 {
582     if ( url.matchIgnoreAsciiCaseAsciiL( "vnd.sun.star.", 13, 0 ) ) {
583         return url.matchIgnoreAsciiCaseAsciiL ( "expand", 6, 13 ) ||
584             url.matchIgnoreAsciiCaseAsciiL ( "script", 6, 13 ) ||
585             url.matchIgnoreAsciiCaseAsciiL ( "tdoc", 4, 13 ) ||
586             url.matchIgnoreAsciiCaseAsciiL ( "uno", 3, 13 );
587     }
588     return sal_False;
589 }
590 
591 
592 // ----------------------------------------------------------------------
lcl_DDE_RelToAbs(const String & rTopic,const String & rBaseURL)593 String lcl_DDE_RelToAbs( const String& rTopic, const String& rBaseURL )
594 {
595     String sRet;
596     INetURLObject aURL( rTopic );
597     if( INET_PROT_NOT_VALID == aURL.GetProtocol() )
598         utl::LocalFileHelper::ConvertSystemPathToURL( rTopic, rBaseURL, sRet );
599     if( !sRet.Len() )
600         sRet = URIHelper::SmartRel2Abs( INetURLObject(rBaseURL), rTopic, URIHelper::GetMaybeFileHdl(), true );
601     return sRet;
602 }
603 
Connect(sfx2::SvBaseLink * pLink)604 sal_Bool SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
605 {
606     SfxObjectShell* pFndShell = 0;
607     sal_uInt16 nUpdateMode = com::sun::star::document::UpdateDocMode::NO_UPDATE;
608     String sTopic, sItem, sReferer;
609     if( pLink->GetLinkManager() &&
610         pLink->GetLinkManager()->GetDisplayNames( pLink, 0, &sTopic, &sItem )
611         && sTopic.Len() )
612     {
613         // erstmal nur ueber die DocumentShells laufen und die mit dem
614         // Namen heraussuchen:
615 
616         com::sun::star::lang::Locale aLocale;
617         MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aLocale );
618         CharClass aCC( aLocale );
619 
620         String sNm( sTopic ), sTmp;
621         aCC.toLower( sNm );
622 
623         TypeId aType( TYPE(SfxObjectShell) );
624 
625         sal_Bool bFirst = sal_True;
626         SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
627         if( pShell && pShell->GetMedium() )
628         {
629             sReferer = pShell->GetMedium()->GetBaseURL();
630             SFX_ITEMSET_ARG( pShell->GetMedium()->GetItemSet(), pItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False );
631             if ( pItem )
632                 nUpdateMode = pItem->GetValue();
633         }
634 
635         String sNmURL( lcl_DDE_RelToAbs( sTopic, sReferer ) );
636         aCC.toLower( sNmURL );
637 
638         if ( !pShell )
639         {
640             bFirst = sal_False;
641             pShell = SfxObjectShell::GetFirst( &aType, sal_False );
642         }
643 
644         while( pShell )
645         {
646             if( !sTmp.Len() )
647             {
648                 sTmp = pShell->GetTitle( SFX_TITLE_FULLNAME );
649                 sTmp = lcl_DDE_RelToAbs(sTmp, sReferer );
650             }
651 
652 
653             aCC.toLower( sTmp );
654             if( sTmp == sNmURL )        // die wollen wir haben
655             {
656                 pFndShell = pShell;
657                 break;
658             }
659 
660             if( bFirst )
661             {
662                 bFirst = sal_False;
663                 pShell = SfxObjectShell::GetFirst( &aType, sal_False );
664             }
665             else
666                 pShell = SfxObjectShell::GetNext( *pShell, &aType, sal_False );
667 
668             sTmp.Erase();
669         }
670     }
671 
672     // empty topics are not allowed - which document is it
673     if( !sTopic.Len() )
674         return sal_False;
675 
676     if( !pFndShell )
677     {
678         // dann versuche die Datei zu laden:
679         INetURLObject aURL( sTopic );
680         INetProtocol eOld = aURL.GetProtocol();
681         aURL.SetURL( sTopic = lcl_DDE_RelToAbs( sTopic, sReferer ) );
682         if( INET_PROT_NOT_VALID != eOld ||
683             INET_PROT_HTTP != aURL.GetProtocol() )
684         {
685             SfxStringItem aName( SID_FILE_NAME, sTopic );
686             SfxBoolItem aMinimized(SID_MINIMIZED, sal_True);
687             SfxBoolItem aHidden(SID_HIDDEN, sal_True);
688             SfxStringItem aTarget( SID_TARGETNAME, String::CreateFromAscii("_blank") );
689             SfxStringItem aReferer( SID_REFERER, sReferer );
690             SfxUInt16Item aUpdate( SID_UPDATEDOCMODE, nUpdateMode );
691             SfxBoolItem aReadOnly(SID_DOC_READONLY, sal_True);
692 
693             // #i14200# (DDE-link crashes wordprocessor)
694             SfxAllItemSet aArgs( SFX_APP()->GetPool() );
695             aArgs.Put(aReferer);
696             aArgs.Put(aTarget);
697             aArgs.Put(aHidden);
698             aArgs.Put(aMinimized);
699             aArgs.Put(aName);
700             aArgs.Put(aUpdate);
701             aArgs.Put(aReadOnly);
702             pFndShell = SfxObjectShell::CreateAndLoadObject( aArgs );
703         }
704     }
705 
706     sal_Bool bRet = sal_False;
707     if( pFndShell )
708     {
709         sfx2::SvLinkSource* pNewSrc = pFndShell->DdeCreateLinkSource( sItem );
710         if( pNewSrc )
711         {
712             bRet = sal_True;
713 
714             ::com::sun::star::datatransfer::DataFlavor aFl;
715             SotExchange::GetFormatDataFlavor( pLink->GetContentType(), aFl );
716 
717             pLink->SetObj( pNewSrc );
718             pNewSrc->AddDataAdvise( pLink, aFl.MimeType,
719                                 sfx2::LINKUPDATE_ONCALL == pLink->GetUpdateMode()
720                                     ? ADVISEMODE_ONLYONCE
721                                     : 0 );
722         }
723     }
724     return bRet;
725 }
726 
727 
728 }
729 
730 
731 
732