xref: /aoo41x/main/sfx2/source/appl/linkmgr2.cxx (revision 8d6615f2)
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:
SvxInternalLink()59 	SvxInternalLink() {}
60 
61     virtual sal_Bool Connect( sfx2::SvBaseLink* );
62 };
63 
64 
SV_IMPL_PTRARR(SvBaseLinks,SvBaseLinkRefPtr)65 SV_IMPL_PTRARR( SvBaseLinks, SvBaseLinkRefPtr )
66 
67 LinkManager::LinkManager(SfxObjectShell* p)
68 	: pPersist(p),
69 	mAutoAskUpdateAllLinks(sal_False),
70 	mUpdateAsked(sal_False)
71 {
72 }
73 
~LinkManager()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 
Remove(SvBaseLink * pLink)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 
Remove(sal_uInt16 nPos,sal_uInt16 nCnt)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 
Insert(SvBaseLink * pLink)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 
InsertLink(SvBaseLink * pLink,sal_uInt16 nObjType,sal_uInt16 nUpdateMode,const String * pName)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 
InsertDDELink(SvBaseLink * pLink,const String & rServer,const String & rTopic,const String & rItem)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 
InsertDDELink(SvBaseLink * pLink)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
GetDisplayNames(const SvBaseLink * pLink,String * pType,String * pFile,String * pLinkStr,String * pFilter) const220 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 
SetAutoAskUpdateAllLinks()282 void LinkManager::SetAutoAskUpdateAllLinks()
283 {
284 	mAutoAskUpdateAllLinks = sal_True;
285     mUpdateAsked = sal_False;
286 }
287 
SetNeverAskUpdateAllLinks()288 void LinkManager::SetNeverAskUpdateAllLinks()
289 {
290     mAutoAskUpdateAllLinks = sal_False;
291     mAllowUpdate = sal_True;
292     mUpdateAsked = sal_True;
293 }
294 
GetUserAllowsLinkUpdate(Window * pParentWin)295 sal_Bool LinkManager::GetUserAllowsLinkUpdate(Window *pParentWin)
296 {
297 	if (!mUpdateAsked)
298 	{
299 		if (QueryBox(pParentWin, WB_YES_NO | WB_DEF_NO, SfxResId(STR_QUERY_UPDATE_LINKS)).Execute() == RET_YES)
300 			mAllowUpdate = sal_True;
301 		else
302 			mAllowUpdate = sal_False;
303 		mUpdateAsked = sal_True;
304 	}
305 	return mAllowUpdate;
306 }
307 
SetUserAllowsLinkUpdate(SvBaseLink * pLink,sal_Bool allows)308 void LinkManager::SetUserAllowsLinkUpdate(SvBaseLink *pLink, sal_Bool allows)
309 {
310 	SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
311 
312 	if (pShell)
313 	{
314 		comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = pShell->getEmbeddedObjectContainer();
315 		rEmbeddedObjectContainer.setUserAllowsLinkUpdate(allows);
316 	}
317 }
318 
319 
UpdateAllLinks(sal_Bool bAskUpdate,sal_Bool,sal_Bool bUpdateGrfLinks,Window * pParentWin)320 void LinkManager::UpdateAllLinks(
321     sal_Bool bAskUpdate,
322     sal_Bool /*bCallErrHdl*/,
323     sal_Bool bUpdateGrfLinks,
324     Window* pParentWin )
325 {
326 	SvStringsDtor aApps, aTopics, aItems;
327 	String sApp, sTopic, sItem;
328 
329 	// erstmal eine Kopie vom Array machen, damit sich updatende Links in
330 	// Links in ... nicht dazwischen funken!!
331 	SvPtrarr aTmpArr( 255, 50 );
332 	sal_uInt16 n;
333 	for( n = 0; n < aLinkTbl.Count(); ++n )
334 	{
335 		SvBaseLink* pLink = *aLinkTbl[ n ];
336 		if( !pLink )
337 		{
338 			Remove( n-- );
339 			continue;
340 		}
341 		aTmpArr.Insert( pLink, aTmpArr.Count() );
342 	}
343 
344 	for( n = 0; n < aTmpArr.Count(); ++n )
345 	{
346 		SvBaseLink* pLink = (SvBaseLink*)aTmpArr[ n ];
347 
348 		// suche erstmal im Array nach dem Eintrag
349 		sal_uInt16 nFndPos = USHRT_MAX;
350 		for( sal_uInt16 i = 0; i < aLinkTbl.Count(); ++i )
351 			if( pLink == *aLinkTbl[ i ] )
352 			{
353 				nFndPos = i;
354 				break;
355 			}
356 
357 		if( USHRT_MAX == nFndPos )
358 			continue;					// war noch nicht vorhanden!
359 
360 		// do not update graphic links yet
361 		if( !pLink->IsVisible() ||
362 			( !bUpdateGrfLinks && OBJECT_CLIENT_GRF == pLink->GetObjType() ))
363 			continue;
364 
365 		sal_Bool allows = sal_True;
366 
367 		if (bAskUpdate)
368 		{
369 			allows = GetUserAllowsLinkUpdate(pParentWin);
370 		}
371 
372 		SetUserAllowsLinkUpdate(pLink, allows);
373 	    bAskUpdate = sal_False;		// one time is OK
374 
375 		if (allows)
376 			pLink->Update();
377 
378 	}
379 }
380 
381 /************************************************************************
382 |*    SvBaseLink::CreateObject()
383 |*
384 |*    Beschreibung
385 *************************************************************************/
386 
CreateObj(SvBaseLink * pLink)387 SvLinkSourceRef LinkManager::CreateObj( SvBaseLink * pLink )
388 {
389 	switch( pLink->GetObjType() )
390 	{
391 	    case OBJECT_CLIENT_FILE:
392 	    case OBJECT_CLIENT_GRF:
393 	    case OBJECT_CLIENT_OLE:
394 		    return new SvFileObject;
395 	    case OBJECT_INTERN:
396 		    return new SvxInternalLink;
397         case OBJECT_CLIENT_DDE:
398 		    return new SvDDEObject;
399 	    default:
400         	return SvLinkSourceRef();
401    	}
402 }
403 
InsertServer(SvLinkSource * pObj)404 sal_Bool LinkManager::InsertServer( SvLinkSource* pObj )
405 {
406 	// keine doppelt einfuegen
407 	if( !pObj || USHRT_MAX != aServerTbl.GetPos( pObj ) )
408 		return sal_False;
409 
410 	aServerTbl.Insert( pObj, aServerTbl.Count() );
411 	return sal_True;
412 }
413 
414 
RemoveServer(SvLinkSource * pObj)415 void LinkManager::RemoveServer( SvLinkSource* pObj )
416 {
417 	sal_uInt16 nPos = aServerTbl.GetPos( pObj );
418 	if( USHRT_MAX != nPos )
419 		aServerTbl.Remove( nPos, 1 );
420 }
421 
422 
MakeLnkName(String & rName,const String * pType,const String & rFile,const String & rLink,const String * pFilter)423 void MakeLnkName( String& rName, const String* pType, const String& rFile,
424 					const String& rLink, const String* pFilter )
425 {
426 	if( pType )
427 		(rName = *pType).EraseLeadingChars().EraseTrailingChars() += cTokenSeperator;
428 	else if( rName.Len() )
429 		rName.Erase();
430 
431 	((rName += rFile).EraseLeadingChars().EraseTrailingChars() +=
432 		cTokenSeperator ).EraseLeadingChars().EraseTrailingChars() += rLink;
433 	if( pFilter )
434 		((rName += cTokenSeperator ) += *pFilter).EraseLeadingChars().EraseTrailingChars();
435 }
436 
InsertFileLink(sfx2::SvBaseLink & rLink,sal_uInt16 nFileType,const String & rFileNm,const String * pFilterNm,const String * pRange)437 sal_Bool LinkManager::InsertFileLink( sfx2::SvBaseLink& rLink,
438 									sal_uInt16 nFileType,
439 									const String& rFileNm,
440 									const String* pFilterNm,
441 									const String* pRange )
442 {
443 	if( !( OBJECT_CLIENT_SO & rLink.GetObjType() ))
444 		return sal_False;
445 
446 	String sCmd( rFileNm );
447 	sCmd += ::sfx2::cTokenSeperator;
448 	if( pRange )
449 		sCmd += *pRange;
450 	if( pFilterNm )
451 		( sCmd += ::sfx2::cTokenSeperator ) += *pFilterNm;
452 
453 	return InsertLink( &rLink, nFileType, sfx2::LINKUPDATE_ONCALL, &sCmd );
454 }
455 
InsertFileLink(sfx2::SvBaseLink & rLink)456 sal_Bool LinkManager::InsertFileLink( sfx2::SvBaseLink& rLink )
457 {
458 	if( OBJECT_CLIENT_FILE == ( OBJECT_CLIENT_FILE & rLink.GetObjType() ))
459 		return InsertLink( &rLink, rLink.GetObjType(), sfx2::LINKUPDATE_ONCALL );
460 	return sal_False;
461 }
462 
463 // eine Uebertragung wird abgebrochen, also alle DownloadMedien canceln
464 // (ist zur Zeit nur fuer die FileLinks interressant!)
CancelTransfers()465 void LinkManager::CancelTransfers()
466 {
467 	SvFileObject* pFileObj;
468 	sfx2::SvBaseLink* pLnk;
469 
470 	const sfx2::SvBaseLinks& rLnks = GetLinks();
471 	for( sal_uInt16 n = rLnks.Count(); n; )
472 		if( 0 != ( pLnk = &(*rLnks[ --n ])) &&
473 			OBJECT_CLIENT_FILE == (OBJECT_CLIENT_FILE & pLnk->GetObjType()) &&
474 			0 != ( pFileObj = (SvFileObject*)pLnk->GetObj() ) )
475 //			0 != ( pFileObj = (SvFileObject*)SvFileObject::ClassFactory()->
476 //									CastAndAddRef( pLnk->GetObj() )) )
477 			pFileObj->CancelTransfers();
478 }
479 
480 	// um Status Informationen aus dem FileObject an den BaseLink zu
481 	// senden, gibt es eine eigene ClipBoardId. Das SvData-Object hat
482 	// dann die entsprechenden Informationen als String.
483 	// Wird zur Zeit fuer FileObject in Verbindung mit JavaScript benoetigt
484 	// - das braucht Informationen ueber Load/Abort/Error
RegisterStatusInfoId()485 sal_uIntPtr LinkManager::RegisterStatusInfoId()
486 {
487 	static sal_uIntPtr nFormat = 0;
488 
489 	if( !nFormat )
490 	{
491 // wie sieht die neue Schnittstelle aus?
492 //		nFormat = Exchange::RegisterFormatName( "StatusInfo vom SvxInternalLink" );
493 		nFormat = SotExchange::RegisterFormatName(
494 					String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM(
495 								"StatusInfo vom SvxInternalLink" )));
496 	}
497 	return nFormat;
498 }
499 
500 // ----------------------------------------------------------------------
501 
GetGraphicFromAny(const String & rMimeType,const::com::sun::star::uno::Any & rValue,Graphic & rGrf)502 sal_Bool LinkManager::GetGraphicFromAny( const String& rMimeType,
503 								const ::com::sun::star::uno::Any & rValue,
504 								Graphic& rGrf )
505 {
506 	sal_Bool bRet = sal_False;
507 	::com::sun::star::uno::Sequence< sal_Int8 > aSeq;
508 	if( rValue.hasValue() && ( rValue >>= aSeq ) )
509 	{
510 		SvMemoryStream aMemStm( (void*)aSeq.getConstArray(), aSeq.getLength(),
511 								STREAM_READ );
512 		aMemStm.Seek( 0 );
513 
514 		switch( SotExchange::GetFormatIdFromMimeType( rMimeType ) )
515 		{
516 		case SOT_FORMATSTR_ID_SVXB:
517 			{
518 				aMemStm >> rGrf;
519 				bRet = sal_True;
520 			}
521 			break;
522 		case FORMAT_GDIMETAFILE:
523 			{
524 				GDIMetaFile aMtf;
525 				aMtf.Read( aMemStm );
526 				rGrf = aMtf;
527 				bRet = sal_True;
528 			}
529 			break;
530 		case FORMAT_BITMAP:
531 			{
532 				Bitmap aBmp;
533                 ReadDIB(aBmp, aMemStm, true);
534 				rGrf = aBmp;
535 				bRet = sal_True;
536 			}
537 			break;
538 		}
539 	}
540 	return bRet;
541 }
542 
543 
544 // ----------------------------------------------------------------------
lcl_DDE_RelToAbs(const String & rTopic,const String & rBaseURL)545 String lcl_DDE_RelToAbs( const String& rTopic, const String& rBaseURL )
546 {
547 	String sRet;
548 	INetURLObject aURL( rTopic );
549 	if( INET_PROT_NOT_VALID == aURL.GetProtocol() )
550         utl::LocalFileHelper::ConvertSystemPathToURL( rTopic, rBaseURL, sRet );
551 	if( !sRet.Len() )
552         sRet = URIHelper::SmartRel2Abs( INetURLObject(rBaseURL), rTopic, URIHelper::GetMaybeFileHdl(), true );
553 	return sRet;
554 }
555 
Connect(sfx2::SvBaseLink * pLink)556 sal_Bool SvxInternalLink::Connect( sfx2::SvBaseLink* pLink )
557 {
558 	SfxObjectShell* pFndShell = 0;
559 	sal_uInt16 nUpdateMode = com::sun::star::document::UpdateDocMode::NO_UPDATE;
560 	String sTopic, sItem, sReferer;
561 	if( pLink->GetLinkManager() &&
562 		pLink->GetLinkManager()->GetDisplayNames( pLink, 0, &sTopic, &sItem )
563 		&& sTopic.Len() )
564 	{
565 		// erstmal nur ueber die DocumentShells laufen und die mit dem
566 		// Namen heraussuchen:
567 
568 	    com::sun::star::lang::Locale aLocale;
569 	    MsLangId::convertLanguageToLocale( LANGUAGE_SYSTEM, aLocale );
570 		CharClass aCC( aLocale );
571 
572         String sNm( sTopic ), sTmp;
573 		aCC.toLower( sNm );
574 
575 		TypeId aType( TYPE(SfxObjectShell) );
576 
577 		sal_Bool bFirst = sal_True;
578         SfxObjectShell* pShell = pLink->GetLinkManager()->GetPersist();
579         if( pShell && pShell->GetMedium() )
580 		{
581             sReferer = pShell->GetMedium()->GetBaseURL();
582 			SFX_ITEMSET_ARG( pShell->GetMedium()->GetItemSet(), pItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False );
583 			if ( pItem )
584 				nUpdateMode = pItem->GetValue();
585 		}
586 
587         String sNmURL( lcl_DDE_RelToAbs( sTopic, sReferer ) );
588 		aCC.toLower( sNmURL );
589 
590 		if ( !pShell )
591 		{
592 			bFirst = sal_False;
593             pShell = SfxObjectShell::GetFirst( &aType, sal_False );
594 		}
595 
596 		while( pShell )
597 		{
598 			if( !sTmp.Len() )
599 			{
600 				sTmp = pShell->GetTitle( SFX_TITLE_FULLNAME );
601                 sTmp = lcl_DDE_RelToAbs(sTmp, sReferer );
602 			}
603 
604 
605 			aCC.toLower( sTmp );
606 			if( sTmp == sNmURL )		// die wollen wir haben
607 			{
608 				pFndShell = pShell;
609 				break;
610 			}
611 
612 			if( bFirst )
613 			{
614 				bFirst = sal_False;
615                 pShell = SfxObjectShell::GetFirst( &aType, sal_False );
616 			}
617 			else
618                 pShell = SfxObjectShell::GetNext( *pShell, &aType, sal_False );
619 
620 			sTmp.Erase();
621 		}
622 	}
623 
624 	// empty topics are not allowed - which document is it
625 	if( !sTopic.Len() )
626 		return sal_False;
627 
628 	if( !pFndShell )
629 	{
630 		// dann versuche die Datei zu laden:
631 		INetURLObject aURL( sTopic );
632 		INetProtocol eOld = aURL.GetProtocol();
633         aURL.SetURL( sTopic = lcl_DDE_RelToAbs( sTopic, sReferer ) );
634 		if( INET_PROT_NOT_VALID != eOld ||
635 			INET_PROT_HTTP != aURL.GetProtocol() )
636 		{
637 			SfxStringItem aName( SID_FILE_NAME, sTopic );
638             SfxBoolItem aMinimized(SID_MINIMIZED, sal_True);
639             SfxBoolItem aHidden(SID_HIDDEN, sal_True);
640             SfxStringItem aTarget( SID_TARGETNAME, String::CreateFromAscii("_blank") );
641 			SfxStringItem aReferer( SID_REFERER, sReferer );
642 			SfxUInt16Item aUpdate( SID_UPDATEDOCMODE, nUpdateMode );
643             SfxBoolItem aReadOnly(SID_DOC_READONLY, sal_True);
644 
645             // #i14200# (DDE-link crashes wordprocessor)
646             SfxAllItemSet aArgs( SFX_APP()->GetPool() );
647             aArgs.Put(aReferer);
648             aArgs.Put(aTarget);
649             aArgs.Put(aHidden);
650             aArgs.Put(aMinimized);
651             aArgs.Put(aName);
652 			aArgs.Put(aUpdate);
653 			aArgs.Put(aReadOnly);
654             pFndShell = SfxObjectShell::CreateAndLoadObject( aArgs );
655 		}
656 	}
657 
658 	sal_Bool bRet = sal_False;
659 	if( pFndShell )
660 	{
661 		sfx2::SvLinkSource* pNewSrc = pFndShell->DdeCreateLinkSource( sItem );
662 		if( pNewSrc )
663 		{
664 			bRet = sal_True;
665 
666 			::com::sun::star::datatransfer::DataFlavor aFl;
667 			SotExchange::GetFormatDataFlavor( pLink->GetContentType(), aFl );
668 
669 			pLink->SetObj( pNewSrc );
670 			pNewSrc->AddDataAdvise( pLink, aFl.MimeType,
671 								sfx2::LINKUPDATE_ONCALL == pLink->GetUpdateMode()
672 									? ADVISEMODE_ONLYONCE
673 									: 0 );
674 		}
675 	}
676 	return bRet;
677 }
678 
679 
680 }
681 
682 
683 
684