Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <comphelper/string.hxx>
21 : #include <sfx2/linkmgr.hxx>
22 : #include <com/sun/star/document/UpdateDocMode.hpp>
23 : #include <sfx2/objsh.hxx>
24 : #include <svl/urihelper.hxx>
25 : #include <sot/formats.hxx>
26 : #include <tools/urlobj.hxx>
27 : #include <sot/exchange.hxx>
28 : #include <tools/debug.hxx>
29 : #include <vcl/msgbox.hxx>
30 : #include <sfx2/lnkbase.hxx>
31 : #include <sfx2/app.hxx>
32 : #include <vcl/graph.hxx>
33 : #include <svl/stritem.hxx>
34 : #include <svl/eitem.hxx>
35 : #include <svl/intitem.hxx>
36 : #include <unotools/localfilehelper.hxx>
37 : #include <i18npool/languagetag.hxx>
38 : #include <sfx2/request.hxx>
39 :
40 : #include "fileobj.hxx"
41 : #include "impldde.hxx"
42 : #include "app.hrc"
43 : #include "sfx2/sfxresid.hxx"
44 :
45 : #include <com/sun/star/lang/XComponent.hpp>
46 : #include <com/sun/star/util/XCloseable.hpp>
47 :
48 : using ::com::sun::star::uno::UNO_QUERY;
49 : using ::com::sun::star::uno::Reference;
50 : using ::com::sun::star::lang::XComponent;
51 : using ::com::sun::star::util::XCloseable;
52 : using ::rtl::OUString;
53 : using ::rtl::OUStringBuffer;
54 :
55 : namespace sfx2
56 : {
57 :
58 0 : class SvxInternalLink : public sfx2::SvLinkSource
59 : {
60 : public:
61 0 : SvxInternalLink() {}
62 :
63 : virtual sal_Bool Connect( sfx2::SvBaseLink* );
64 : };
65 :
66 :
67 483 : LinkManager::LinkManager(SfxObjectShell* p)
68 483 : : pPersist( p )
69 : {
70 483 : }
71 :
72 :
73 452 : LinkManager::~LinkManager()
74 : {
75 226 : for( sal_uInt16 n = 0; n < aLinkTbl.size(); ++n)
76 : {
77 0 : SvBaseLinkRef* pTmp = aLinkTbl[ n ];
78 0 : if( pTmp->Is() )
79 : {
80 0 : (*pTmp)->Disconnect();
81 0 : (*pTmp)->SetLinkManager( NULL );
82 : }
83 0 : delete pTmp;
84 : }
85 226 : }
86 :
87 0 : void LinkManager::InsertCachedComp(const Reference<XComponent>& xComp)
88 : {
89 0 : maCachedComps.push_back(xComp);
90 0 : }
91 :
92 0 : void LinkManager::CloseCachedComps()
93 : {
94 0 : CompVector::iterator itr = maCachedComps.begin(), itrEnd = maCachedComps.end();
95 0 : for (; itr != itrEnd; ++itr)
96 : {
97 0 : Reference<XCloseable> xCloseable(*itr, UNO_QUERY);
98 0 : if (!xCloseable.is())
99 0 : continue;
100 :
101 0 : xCloseable->close(true);
102 0 : }
103 0 : maCachedComps.clear();
104 0 : }
105 :
106 : //--------------------------------------------------------------------------
107 :
108 1 : void LinkManager::Remove( SvBaseLink *pLink )
109 : {
110 : // No duplicate links inserted
111 1 : int bFound = sal_False;
112 2 : for( sal_uInt16 n = 0; n < aLinkTbl.size(); )
113 : {
114 1 : SvBaseLinkRef* pTmp = aLinkTbl[ n ];
115 1 : if( pLink == *pTmp )
116 : {
117 1 : (*pTmp)->Disconnect();
118 1 : (*pTmp)->SetLinkManager( NULL );
119 1 : (*pTmp).Clear();
120 1 : bFound = sal_True;
121 : }
122 :
123 : // Remove empty ones if they exist
124 1 : if( !pTmp->Is() )
125 : {
126 1 : delete pTmp;
127 1 : aLinkTbl.erase( aLinkTbl.begin() + n );
128 1 : if( bFound )
129 2 : return ;
130 : }
131 : else
132 0 : ++n;
133 : }
134 : }
135 :
136 :
137 0 : void LinkManager::Remove( sal_uInt16 nPos, sal_uInt16 nCnt )
138 : {
139 0 : if( nCnt && nPos < aLinkTbl.size() )
140 : {
141 0 : if (sal::static_int_cast<size_t>(nPos + nCnt) > aLinkTbl.size())
142 0 : nCnt = aLinkTbl.size() - nPos;
143 :
144 0 : for( sal_uInt16 n = nPos; n < nPos + nCnt; ++n)
145 : {
146 0 : SvBaseLinkRef* pTmp = aLinkTbl[ n ];
147 0 : if( pTmp->Is() )
148 : {
149 0 : (*pTmp)->Disconnect();
150 0 : (*pTmp)->SetLinkManager( NULL );
151 : }
152 0 : delete pTmp;
153 : }
154 0 : aLinkTbl.erase( aLinkTbl.begin() + nPos, aLinkTbl.begin() + nPos + nCnt );
155 : }
156 0 : }
157 :
158 :
159 3 : sal_Bool LinkManager::Insert( SvBaseLink* pLink )
160 : {
161 : // No duplicate links inserted
162 3 : for( sal_uInt16 n = 0; n < aLinkTbl.size(); ++n )
163 : {
164 0 : SvBaseLinkRef* pTmp = aLinkTbl[ n ];
165 0 : if( !pTmp->Is() )
166 : {
167 0 : delete pTmp;
168 0 : aLinkTbl.erase( aLinkTbl.begin() + n-- );
169 : }
170 :
171 0 : if( pLink == *pTmp )
172 0 : return sal_False;
173 : }
174 :
175 3 : SvBaseLinkRef* pTmp = new SvBaseLinkRef( pLink );
176 3 : pLink->SetLinkManager( this );
177 3 : aLinkTbl.push_back( pTmp );
178 3 : return sal_True;
179 : }
180 :
181 :
182 3 : sal_Bool LinkManager::InsertLink( SvBaseLink * pLink,
183 : sal_uInt16 nObjType,
184 : sal_uInt16 nUpdateMode,
185 : const String* pName )
186 : {
187 : // This First
188 3 : pLink->SetObjType( nObjType );
189 3 : if( pName )
190 3 : pLink->SetName( *pName );
191 3 : pLink->SetUpdateMode( nUpdateMode );
192 3 : return Insert( pLink );
193 : }
194 :
195 :
196 0 : sal_Bool LinkManager::InsertDDELink( SvBaseLink * pLink,
197 : const String& rServer,
198 : const String& rTopic,
199 : const String& rItem )
200 : {
201 0 : if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
202 0 : return sal_False;
203 :
204 0 : String sCmd;
205 0 : ::sfx2::MakeLnkName( sCmd, &rServer, rTopic, rItem );
206 :
207 0 : pLink->SetObjType( OBJECT_CLIENT_DDE );
208 0 : pLink->SetName( sCmd );
209 0 : return Insert( pLink );
210 : }
211 :
212 :
213 0 : sal_Bool LinkManager::InsertDDELink( SvBaseLink * pLink )
214 : {
215 : DBG_ASSERT( OBJECT_CLIENT_SO & pLink->GetObjType(), "no OBJECT_CLIENT_SO" );
216 0 : if( !( OBJECT_CLIENT_SO & pLink->GetObjType() ) )
217 0 : return sal_False;
218 :
219 0 : if( pLink->GetObjType() == OBJECT_CLIENT_SO )
220 0 : pLink->SetObjType( OBJECT_CLIENT_DDE );
221 :
222 0 : return Insert( pLink );
223 : }
224 :
225 :
226 : // Obtain the string for the dialog
227 2 : bool LinkManager::GetDisplayNames( const SvBaseLink * pLink,
228 : String* pType,
229 : String* pFile,
230 : String* pLinkStr,
231 : String* pFilter ) const
232 : {
233 2 : bool bRet = false;
234 2 : const String sLNm( pLink->GetLinkSourceName() );
235 2 : if( sLNm.Len() )
236 : {
237 2 : switch( pLink->GetObjType() )
238 : {
239 : case OBJECT_CLIENT_FILE:
240 : case OBJECT_CLIENT_GRF:
241 : case OBJECT_CLIENT_OLE:
242 : {
243 2 : sal_uInt16 nPos = 0;
244 2 : String sFile( sLNm.GetToken( 0, ::sfx2::cTokenSeperator, nPos ) );
245 2 : String sRange( sLNm.GetToken( 0, ::sfx2::cTokenSeperator, nPos ) );
246 :
247 2 : if( pFile )
248 2 : *pFile = sFile;
249 2 : if( pLinkStr )
250 0 : *pLinkStr = sRange;
251 2 : if( pFilter )
252 2 : *pFilter = sLNm.Copy( nPos );
253 :
254 2 : if( pType )
255 : {
256 0 : sal_uInt16 nObjType = pLink->GetObjType();
257 : *pType = SfxResId(
258 : ( OBJECT_CLIENT_FILE == nObjType || OBJECT_CLIENT_OLE == nObjType )
259 : ? RID_SVXSTR_FILELINK
260 0 : : RID_SVXSTR_GRAFIKLINK).toString();
261 : }
262 2 : bRet = true;
263 : }
264 2 : break;
265 : case OBJECT_CLIENT_DDE:
266 : {
267 0 : sal_uInt16 nTmp = 0;
268 0 : String sCmd( sLNm );
269 0 : String sServer( sCmd.GetToken( 0, cTokenSeperator, nTmp ) );
270 0 : String sTopic( sCmd.GetToken( 0, cTokenSeperator, nTmp ) );
271 :
272 0 : if( pType )
273 0 : *pType = sServer;
274 0 : if( pFile )
275 0 : *pFile = sTopic;
276 0 : if( pLinkStr )
277 0 : *pLinkStr = sCmd.Copy( nTmp );
278 0 : bRet = true;
279 : }
280 0 : break;
281 : default:
282 0 : break;
283 : }
284 : }
285 :
286 2 : return bRet;
287 : }
288 :
289 0 : bool LinkManager::GetDisplayNames(
290 : const SvBaseLink* pLink, rtl::OUString* pType, rtl::OUString* pFile,
291 : rtl::OUString* pLinkStr, rtl::OUString* pFilter) const
292 : {
293 0 : String aType, aFile, aLinkStr, aFilter;
294 0 : bool bRet = GetDisplayNames(pLink, &aType, &aFile, &aLinkStr, &aFilter);
295 0 : if (pType)
296 0 : *pType = aType;
297 0 : if (pFile)
298 0 : *pFile = aFile;
299 0 : if (pLinkStr)
300 0 : *pLinkStr = aLinkStr;
301 0 : if (pFilter)
302 0 : *pFilter = aFilter;
303 0 : return bRet;
304 : }
305 :
306 0 : void LinkManager::UpdateAllLinks(
307 : bool bAskUpdate,
308 : bool /*bCallErrHdl*/,
309 : bool bUpdateGrfLinks,
310 : Window* pParentWin )
311 : {
312 : // First make a copy of the array in order to update links
313 : // links in ... no contact between them!
314 0 : std::vector<SvBaseLink*> aTmpArr;
315 : sal_uInt16 n;
316 0 : for( n = 0; n < aLinkTbl.size(); ++n )
317 : {
318 0 : SvBaseLink* pLink = *aLinkTbl[ n ];
319 0 : if( !pLink )
320 : {
321 0 : Remove( n-- );
322 0 : continue;
323 : }
324 0 : aTmpArr.push_back( pLink );
325 : }
326 :
327 0 : for( n = 0; n < aTmpArr.size(); ++n )
328 : {
329 0 : SvBaseLink* pLink = aTmpArr[ n ];
330 :
331 : // search first in the array after the entry
332 0 : sal_uInt16 nFndPos = USHRT_MAX;
333 0 : for( sal_uInt16 i = 0; i < aLinkTbl.size(); ++i )
334 0 : if( pLink == *aLinkTbl[ i ] )
335 : {
336 0 : nFndPos = i;
337 0 : break;
338 : }
339 :
340 0 : if( USHRT_MAX == nFndPos )
341 0 : continue; // was not available!
342 :
343 : // Graphic-Links not to update yet
344 0 : if( !pLink->IsVisible() ||
345 0 : ( !bUpdateGrfLinks && OBJECT_CLIENT_GRF == pLink->GetObjType() ))
346 0 : continue;
347 :
348 0 : if( bAskUpdate )
349 : {
350 0 : int nRet = QueryBox( pParentWin, WB_YES_NO | WB_DEF_YES, SfxResId( STR_QUERY_UPDATE_LINKS ).toString() ).Execute();
351 0 : if( RET_YES != nRet )
352 0 : return ; // nothing should be updated
353 0 : bAskUpdate = false; // once is enough
354 : }
355 :
356 0 : pLink->Update();
357 : }
358 0 : CloseCachedComps();
359 : }
360 :
361 : //--------------------------------------------------------------------------
362 :
363 2 : SvLinkSourceRef LinkManager::CreateObj( SvBaseLink * pLink )
364 : {
365 2 : switch( pLink->GetObjType() )
366 : {
367 : case OBJECT_CLIENT_FILE:
368 : case OBJECT_CLIENT_GRF:
369 : case OBJECT_CLIENT_OLE:
370 2 : return new SvFileObject;
371 : case OBJECT_INTERN:
372 0 : return new SvxInternalLink;
373 : case OBJECT_CLIENT_DDE:
374 0 : return new SvDDEObject;
375 : default:
376 0 : return SvLinkSourceRef();
377 : }
378 : }
379 :
380 0 : sal_Bool LinkManager::InsertServer( SvLinkSource* pObj )
381 : {
382 : // no duplicate inserts
383 0 : if( !pObj )
384 0 : return sal_False;
385 :
386 0 : return aServerTbl.insert( pObj ).second;
387 : }
388 :
389 :
390 0 : void LinkManager::RemoveServer( SvLinkSource* pObj )
391 : {
392 0 : aServerTbl.erase( pObj );
393 0 : }
394 :
395 :
396 0 : void MakeLnkName( String& rName, const String* pType, const String& rFile,
397 : const String& rLink, const String* pFilter )
398 : {
399 0 : if( pType )
400 : {
401 0 : rName = comphelper::string::strip(*pType, ' ');
402 0 : rName += cTokenSeperator;
403 : }
404 0 : else if( rName.Len() )
405 0 : rName.Erase();
406 :
407 0 : rName += rFile;
408 :
409 0 : rName = comphelper::string::strip(rName, ' ');
410 0 : rName += cTokenSeperator;
411 0 : rName = comphelper::string::strip(rName, ' ');
412 0 : rName += rLink;
413 0 : if( pFilter )
414 : {
415 0 : rName += cTokenSeperator;
416 0 : rName += *pFilter;
417 0 : rName = comphelper::string::strip(rName, ' ');
418 : }
419 0 : }
420 :
421 4757 : void LinkManager::ReconnectDdeLink(SfxObjectShell& rServer)
422 : {
423 4757 : SfxMedium* pMed = rServer.GetMedium();
424 4757 : if (!pMed)
425 4757 : return;
426 :
427 4757 : const ::sfx2::SvBaseLinks& rLinks = GetLinks();
428 4757 : sal_uInt16 n = rLinks.size();
429 :
430 4757 : for (sal_uInt16 i = 0; i < n; ++i)
431 : {
432 0 : ::sfx2::SvBaseLink* p = *rLinks[i];
433 0 : String aType, aFile, aLink, aFilter;
434 0 : if (!GetDisplayNames(p, &aType, &aFile, &aLink, &aFilter))
435 0 : continue;
436 :
437 0 : if (!aType.EqualsAscii("soffice"))
438 : // DDE connections between OOo apps are always named 'soffice'.
439 0 : continue;
440 :
441 0 : rtl::OUString aTmp;
442 0 : OUString aURL = aFile;
443 0 : if (utl::LocalFileHelper::ConvertPhysicalNameToURL(aFile, aTmp))
444 0 : aURL = aTmp;
445 :
446 0 : if (!aURL.equalsIgnoreAsciiCase(pMed->GetName()))
447 : // This DDE link is not associated with this server shell... Skip it.
448 0 : continue;
449 :
450 0 : if (!aLink.Len())
451 0 : continue;
452 :
453 0 : LinkServerShell(aLink, rServer, *p);
454 0 : }
455 : }
456 :
457 0 : void LinkManager::LinkServerShell(const OUString& rPath, SfxObjectShell& rServer, ::sfx2::SvBaseLink& rLink) const
458 : {
459 0 : ::sfx2::SvLinkSource* pSrvSrc = rServer.DdeCreateLinkSource(rPath);
460 0 : if (pSrvSrc)
461 : {
462 0 : ::com::sun::star::datatransfer::DataFlavor aFl;
463 0 : SotExchange::GetFormatDataFlavor(rLink.GetContentType(), aFl);
464 0 : rLink.SetObj(pSrvSrc);
465 : pSrvSrc->AddDataAdvise(
466 : &rLink, aFl.MimeType,
467 0 : sfx2::LINKUPDATE_ONCALL == rLink.GetUpdateMode() ? ADVISEMODE_ONLYONCE : 0);
468 : }
469 0 : }
470 :
471 3 : bool LinkManager::InsertFileLink( sfx2::SvBaseLink& rLink,
472 : sal_uInt16 nFileType,
473 : const String& rFileNm,
474 : const String* pFilterNm,
475 : const String* pRange )
476 : {
477 3 : if( !( OBJECT_CLIENT_SO & rLink.GetObjType() ))
478 0 : return false;
479 :
480 3 : String sCmd( rFileNm );
481 3 : sCmd += ::sfx2::cTokenSeperator;
482 3 : if( pRange )
483 0 : sCmd += *pRange;
484 3 : if( pFilterNm )
485 2 : ( sCmd += ::sfx2::cTokenSeperator ) += *pFilterNm;
486 :
487 3 : return InsertLink( &rLink, nFileType, sfx2::LINKUPDATE_ONCALL, &sCmd );
488 : }
489 :
490 0 : bool LinkManager::InsertFileLink(
491 : sfx2::SvBaseLink& rLink, sal_uInt16 nFileType, const rtl::OUString& rFileNm,
492 : const rtl::OUString* pFilterNm, const rtl::OUString* pRange)
493 : {
494 0 : if (!(OBJECT_CLIENT_SO & rLink.GetObjType()))
495 0 : return false;
496 :
497 0 : rtl::OUStringBuffer aBuf;
498 0 : aBuf.append(rFileNm);
499 0 : aBuf.append(sfx2::cTokenSeperator);
500 :
501 0 : if (pRange)
502 0 : aBuf.append(*pRange);
503 :
504 0 : if (pFilterNm)
505 : {
506 0 : aBuf.append(sfx2::cTokenSeperator);
507 0 : aBuf.append(*pFilterNm);
508 : }
509 :
510 0 : String aCmd = aBuf.makeStringAndClear();
511 0 : return InsertLink(&rLink, nFileType, sfx2::LINKUPDATE_ONCALL, &aCmd);
512 : }
513 :
514 : // A transfer is aborted, so cancel all download media
515 : // (for now this is only of interest for the file links!)
516 63 : void LinkManager::CancelTransfers()
517 : {
518 : SvFileObject* pFileObj;
519 : sfx2::SvBaseLink* pLnk;
520 :
521 63 : const sfx2::SvBaseLinks& rLnks = GetLinks();
522 126 : for( sal_uInt16 n = rLnks.size(); n; )
523 0 : if( 0 != ( pLnk = &(*rLnks[ --n ])) &&
524 0 : OBJECT_CLIENT_FILE == (OBJECT_CLIENT_FILE & pLnk->GetObjType()) &&
525 : 0 != ( pFileObj = (SvFileObject*)pLnk->GetObj() ) )
526 0 : pFileObj->CancelTransfers();
527 63 : }
528 : // For the purpose of sending Status information from the file object to
529 : // the base link, there exist a dedicated ClipBoardId. The SvData-object
530 : // gets the appropriate information as a string
531 : // For now this is required for file object in conjunction with JavaScript
532 : // - needs information about Load/Abort/Error
533 0 : sal_uIntPtr LinkManager::RegisterStatusInfoId()
534 : {
535 : static sal_uIntPtr nFormat = 0;
536 :
537 0 : if( !nFormat )
538 : {
539 : nFormat = SotExchange::RegisterFormatName(
540 0 : rtl::OUString("StatusInfo from SvxInternalLink"));
541 : }
542 0 : return nFormat;
543 : }
544 :
545 : // ----------------------------------------------------------------------
546 :
547 0 : sal_Bool LinkManager::GetGraphicFromAny( const String& rMimeType,
548 : const ::com::sun::star::uno::Any & rValue,
549 : Graphic& rGrf )
550 : {
551 0 : sal_Bool bRet = sal_False;
552 0 : ::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
553 0 : if( rValue.hasValue() && ( rValue >>= aSeq ) )
554 : {
555 0 : SvMemoryStream aMemStm( (void*)aSeq.getConstArray(), aSeq.getLength(),
556 0 : STREAM_READ );
557 0 : aMemStm.Seek( 0 );
558 :
559 0 : switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
560 : {
561 : case SOT_FORMATSTR_ID_SVXB:
562 : {
563 0 : aMemStm >> rGrf;
564 0 : bRet = sal_True;
565 : }
566 0 : break;
567 : case FORMAT_GDIMETAFILE:
568 : {
569 0 : GDIMetaFile aMtf;
570 0 : aMtf.Read( aMemStm );
571 0 : rGrf = aMtf;
572 0 : bRet = sal_True;
573 : }
574 0 : break;
575 : case FORMAT_BITMAP:
576 : {
577 0 : Bitmap aBmp;
578 0 : aMemStm >> aBmp;
579 0 : rGrf = aBmp;
580 0 : bRet = sal_True;
581 : }
582 0 : break;
583 0 : }
584 : }
585 0 : return bRet;
586 : }
587 :
588 :
589 : // ----------------------------------------------------------------------
590 0 : String lcl_DDE_RelToAbs( const String& rTopic, const String& rBaseURL )
591 : {
592 0 : String sRet;
593 0 : INetURLObject aURL( rTopic );
594 0 : if( INET_PROT_NOT_VALID == aURL.GetProtocol() )
595 0 : utl::LocalFileHelper::ConvertSystemPathToURL( rTopic, rBaseURL, sRet );
596 0 : if( !sRet.Len() )
597 0 : sRet = URIHelper::SmartRel2Abs( INetURLObject(rBaseURL), rTopic, URIHelper::GetMaybeFileHdl(), true );
598 0 : return sRet;
599 : }
600 :
601 0 : sal_Bool SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
602 : {
603 0 : SfxObjectShell* pFndShell = 0;
604 0 : sal_uInt16 nUpdateMode = com::sun::star::document::UpdateDocMode::NO_UPDATE;
605 0 : String sTopic, sItem, sReferer;
606 0 : LinkManager* pLinkMgr = pLink->GetLinkManager();
607 0 : if (pLinkMgr && pLinkMgr->GetDisplayNames(pLink, 0, &sTopic, &sItem) && sTopic.Len())
608 : {
609 : // first only loop over the DocumentShells the shells and find those
610 : // with the name:
611 0 : CharClass aCC( LanguageTag( LANGUAGE_SYSTEM) );
612 :
613 0 : TypeId aType( TYPE(SfxObjectShell) );
614 :
615 0 : sal_Bool bFirst = sal_True;
616 0 : SfxObjectShell* pShell = pLinkMgr->GetPersist();
617 0 : if( pShell && pShell->GetMedium() )
618 : {
619 0 : sReferer = pShell->GetMedium()->GetBaseURL();
620 0 : SFX_ITEMSET_ARG( pShell->GetMedium()->GetItemSet(), pItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False );
621 0 : if ( pItem )
622 0 : nUpdateMode = pItem->GetValue();
623 : }
624 :
625 0 : String sNmURL(aCC.lowercase(lcl_DDE_RelToAbs(sTopic, sReferer)));
626 :
627 0 : if ( !pShell )
628 : {
629 0 : bFirst = sal_False;
630 0 : pShell = SfxObjectShell::GetFirst( &aType, sal_False );
631 : }
632 :
633 0 : String sTmp;
634 0 : while( pShell )
635 : {
636 0 : if( !sTmp.Len() )
637 : {
638 0 : sTmp = pShell->GetTitle( SFX_TITLE_FULLNAME );
639 0 : sTmp = lcl_DDE_RelToAbs(sTmp, sReferer );
640 : }
641 :
642 :
643 0 : sTmp = aCC.lowercase( sTmp );
644 0 : if( sTmp == sNmURL ) // we want these
645 : {
646 0 : pFndShell = pShell;
647 0 : break;
648 : }
649 :
650 0 : if( bFirst )
651 : {
652 0 : bFirst = sal_False;
653 0 : pShell = SfxObjectShell::GetFirst( &aType, sal_False );
654 : }
655 : else
656 0 : pShell = SfxObjectShell::GetNext( *pShell, &aType, sal_False );
657 :
658 0 : sTmp.Erase();
659 0 : }
660 : }
661 :
662 : // empty topics are not allowed - which document is it
663 0 : if( !sTopic.Len() )
664 0 : return sal_False;
665 :
666 0 : if (pFndShell)
667 : {
668 0 : sfx2::SvLinkSource* pNewSrc = pFndShell->DdeCreateLinkSource( sItem );
669 0 : if( pNewSrc )
670 : {
671 0 : ::com::sun::star::datatransfer::DataFlavor aFl;
672 0 : SotExchange::GetFormatDataFlavor( pLink->GetContentType(), aFl );
673 :
674 0 : pLink->SetObj( pNewSrc );
675 : pNewSrc->AddDataAdvise( pLink, aFl.MimeType,
676 0 : sfx2::LINKUPDATE_ONCALL == pLink->GetUpdateMode()
677 : ? ADVISEMODE_ONLYONCE
678 0 : : 0 );
679 0 : return true;
680 : }
681 : }
682 : else
683 : {
684 : // then try to download the file:
685 0 : INetURLObject aURL( sTopic );
686 0 : INetProtocol eOld = aURL.GetProtocol();
687 0 : aURL.SetURL( sTopic = lcl_DDE_RelToAbs( sTopic, sReferer ) );
688 0 : if( INET_PROT_NOT_VALID != eOld ||
689 0 : INET_PROT_HTTP != aURL.GetProtocol() )
690 : {
691 0 : SfxStringItem aName( SID_FILE_NAME, sTopic );
692 0 : SfxBoolItem aMinimized(SID_MINIMIZED, sal_True);
693 0 : SfxBoolItem aHidden(SID_HIDDEN, sal_True);
694 0 : SfxStringItem aTarget( SID_TARGETNAME, rtl::OUString("_blank") );
695 0 : SfxStringItem aReferer( SID_REFERER, sReferer );
696 0 : SfxUInt16Item aUpdate( SID_UPDATEDOCMODE, nUpdateMode );
697 0 : SfxBoolItem aReadOnly(SID_DOC_READONLY, false);
698 :
699 : // Disable automatic re-connection to avoid this link instance
700 : // being destroyed at re-connection.
701 0 : SfxBoolItem aDdeConnect(SID_DDE_RECONNECT_ONLOAD, false);
702 :
703 : // #i14200# (DDE-link crashes wordprocessor)
704 0 : SfxAllItemSet aArgs( SFX_APP()->GetPool() );
705 0 : aArgs.Put(aReferer);
706 0 : aArgs.Put(aTarget);
707 0 : aArgs.Put(aHidden);
708 0 : aArgs.Put(aMinimized);
709 0 : aArgs.Put(aName);
710 0 : aArgs.Put(aUpdate);
711 0 : aArgs.Put(aReadOnly);
712 0 : aArgs.Put(aDdeConnect);
713 0 : Reference<XComponent> xComp = SfxObjectShell::CreateAndLoadComponent(aArgs);
714 0 : pFndShell = SfxObjectShell::GetShellFromComponent(xComp);
715 0 : if (xComp.is() && pFndShell)
716 : {
717 0 : pLinkMgr->InsertCachedComp(xComp);
718 0 : pLinkMgr->LinkServerShell(sItem, *pFndShell, *pLink);
719 0 : return true;
720 0 : }
721 0 : }
722 : }
723 :
724 0 : return false;
725 : }
726 :
727 :
728 : }
729 :
730 :
731 :
732 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|