xref: /aoo4110/main/sfx2/source/appl/lnkbase2.cxx (revision b1cdbd2c)
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 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26 
27 
28 #include <sfx2/lnkbase.hxx>
29 #include <sot/exchange.hxx>
30 #include <com/sun/star/uno/Any.hxx>
31 #include <com/sun/star/uno/Sequence.hxx>
32 #include <vcl/msgbox.hxx>
33 #include <sfx2/linkmgr.hxx>
34 #include <vcl/svapp.hxx>
35 #include "app.hrc"
36 #include "sfx2/sfxresid.hxx"
37 #include <sfx2/filedlghelper.hxx>
38 #include <tools/debug.hxx>
39 #include <svl/svdde.hxx>
40 
41 using namespace ::com::sun::star::uno;
42 
43 namespace sfx2
44 {
45 
46 TYPEINIT0( SvBaseLink )
47 
48 static DdeTopic* FindTopic( const String &, sal_uInt16* = 0 );
49 
50 class  ImplDdeItem;
51 
52 struct BaseLink_Impl
53 {
54     Link                m_aEndEditLink;
55     LinkManager*      m_pLinkMgr;
56     Window*             m_pParentWin;
57     FileDialogHelper*   m_pFileDlg;
58     bool                m_bIsConnect;
59 
BaseLink_Implsfx2::BaseLink_Impl60     BaseLink_Impl() :
61           m_pLinkMgr( NULL )
62         , m_pParentWin( NULL )
63         , m_pFileDlg( NULL )
64         , m_bIsConnect( false )
65         {}
66 
~BaseLink_Implsfx2::BaseLink_Impl67     ~BaseLink_Impl()
68         { delete m_pFileDlg; }
69 };
70 
71 // nur fuer die interne Verwaltung
72 struct ImplBaseLinkData
73 {
74 	struct tClientType
75 	{
76 		// gilt fuer alle Links
77 		sal_uIntPtr				nCntntType; // Update Format
78 		// nicht Ole-Links
79 		sal_Bool 			bIntrnlLnk; // ist es ein interner Link
80 		sal_uInt16 			nUpdateMode;// UpdateMode
81 	};
82 
83 	struct tDDEType
84 	{
85 		ImplDdeItem* pItem;
86 	};
87 
88 	union {
89 		tClientType ClientType;
90 		tDDEType DDEType;
91 	};
ImplBaseLinkDatasfx2::ImplBaseLinkData92 	ImplBaseLinkData()
93 	{
94 		ClientType.nCntntType = 0;
95 		ClientType.bIntrnlLnk = sal_False;
96 		ClientType.nUpdateMode = 0;
97 		DDEType.pItem = NULL;
98 	}
99 };
100 
101 
102 class ImplDdeItem : public DdeGetPutItem
103 {
104 	SvBaseLink* pLink;
105 	DdeData aData;
106 	Sequence< sal_Int8 > aSeq;		    // Datacontainer for DdeData !!!
107 	sal_Bool bIsValidData : 1;
108 	sal_Bool bIsInDTOR : 1;
109 public:
ImplDdeItem(SvBaseLink & rLink,const String & rStr)110 	ImplDdeItem( SvBaseLink& rLink, const String& rStr )
111 		: DdeGetPutItem( rStr ), pLink( &rLink ), bIsValidData( sal_False ),
112 		bIsInDTOR( sal_False )
113 	{}
114 	virtual ~ImplDdeItem();
115 
116 	virtual DdeData* Get( sal_uIntPtr );
117 	virtual sal_Bool Put( const DdeData* );
118 	virtual void AdviseLoop( sal_Bool );
119 
Notify()120 	void Notify()
121 	{
122 		bIsValidData = sal_False;
123 		DdeGetPutItem::NotifyClient();
124 	}
125 
IsInDTOR() const126 	sal_Bool IsInDTOR() const { return bIsInDTOR; }
127 };
128 
129 
130 /************************************************************************
131 |*	  SvBaseLink::SvBaseLink()
132 |*
133 |*	  Beschreibung
134 *************************************************************************/
135 
SvBaseLink()136 SvBaseLink::SvBaseLink()
137 :   SvRefBase(),
138     xObj(),
139     aLinkName(),
140     pImpl(new BaseLink_Impl()),
141     nObjType(OBJECT_CLIENT_SO),
142     bVisible(sal_True),
143     bSynchron(sal_True),
144     bUseCache(sal_True),
145     bWasLastEditOK(sal_False),
146     pImplData(new ImplBaseLinkData),
147     m_bIsReadOnly(false),
148     m_xInputStreamToLoadFrom()
149 {
150 }
151 
152 /************************************************************************
153 |*	  SvBaseLink::SvBaseLink()
154 |*
155 |*	  Beschreibung
156 *************************************************************************/
157 
SvBaseLink(sal_uInt16 nUpdateMode,sal_uIntPtr nContentType)158 SvBaseLink::SvBaseLink( sal_uInt16 nUpdateMode, sal_uIntPtr nContentType )
159 :   SvRefBase(),
160     xObj(),
161     aLinkName(),
162     pImpl(new BaseLink_Impl()),
163     nObjType(OBJECT_CLIENT_SO),
164     bVisible(sal_True),
165     bSynchron(sal_True),
166     bUseCache(sal_True),
167     bWasLastEditOK(sal_False),
168     pImplData(new ImplBaseLinkData),
169     m_bIsReadOnly(false),
170     m_xInputStreamToLoadFrom()
171 {
172 	// falls es ein Ole-Link wird,
173 	pImplData->ClientType.nUpdateMode = nUpdateMode;
174 	pImplData->ClientType.nCntntType = nContentType;
175 	pImplData->ClientType.bIntrnlLnk = sal_False;
176 }
177 
178 /************************************************************************
179 |*	  SvBaseLink::SvBaseLink()
180 |*
181 |*	  Beschreibung
182 *************************************************************************/
183 
SvBaseLink(const String & rLinkName,sal_uInt16 nObjectType,SvLinkSource * pObj)184 SvBaseLink::SvBaseLink( const String& rLinkName, sal_uInt16 nObjectType, SvLinkSource* pObj )
185 :   SvRefBase(),
186     xObj(),
187     aLinkName(rLinkName),
188     pImpl(0),
189     nObjType(nObjectType),
190     bVisible(sal_True),
191     bSynchron(sal_True),
192     bUseCache(sal_True),
193     bWasLastEditOK(sal_False),
194     pImplData(new ImplBaseLinkData),
195     m_bIsReadOnly(false),
196     m_xInputStreamToLoadFrom()
197 {
198 	if( !pObj )
199 	{
200 		DBG_ASSERT( pObj, "Wo ist mein zu linkendes Object" );
201 		return;
202 	}
203 
204 	if( OBJECT_DDE_EXTERN == nObjType )
205 	{
206 		sal_uInt16 nItemStt = 0;
207 		DdeTopic* pTopic = FindTopic( aLinkName, &nItemStt );
208 		if( pTopic )
209 		{
210 			// dann haben wir alles zusammen
211 			// MM hat gefummelt ???
212 			// MM_TODO wie kriege ich den Namen
213 			String aStr = aLinkName; // xLinkName->GetDisplayName();
214 			aStr = aStr.Copy( nItemStt );
215 			pImplData->DDEType.pItem = new ImplDdeItem( *this, aStr );
216 			pTopic->InsertItem( pImplData->DDEType.pItem );
217 
218 			// dann koennen wir uns auch das Advise merken
219 			xObj = pObj;
220 		}
221 	}
222     else if( pObj->Connect( this ) )
223 		xObj = pObj;
224 }
225 
226 /************************************************************************
227 |*	  SvBaseLink::~SvBaseLink()
228 |*
229 |*	  Beschreibung
230 *************************************************************************/
231 
~SvBaseLink()232 SvBaseLink::~SvBaseLink()
233 {
234 	Disconnect();
235 
236 	switch( nObjType )
237 	{
238 	case OBJECT_DDE_EXTERN:
239 		if( !pImplData->DDEType.pItem->IsInDTOR() )
240 			delete pImplData->DDEType.pItem;
241 		break;
242 	}
243 
244 	delete pImplData;
245 
246     if(pImpl)
247     {
248         delete pImpl;
249     }
250 }
251 
IMPL_LINK(SvBaseLink,EndEditHdl,String *,_pNewName)252 IMPL_LINK( SvBaseLink, EndEditHdl, String*, _pNewName )
253 {
254     if(pImpl)
255     {
256         String sNewName;
257         if ( _pNewName )
258             sNewName = *_pNewName;
259         if ( !ExecuteEdit( sNewName ) )
260             sNewName.Erase();
261         bWasLastEditOK = ( sNewName.Len() > 0 );
262         if ( pImpl->m_aEndEditLink.IsSet() )
263             pImpl->m_aEndEditLink.Call( this );
264     }
265     else
266     {
267         OSL_ENSURE(false, "No pImpl (!)");
268     }
269     return 0;
270 }
271 
272 /************************************************************************
273 |*	  SvBaseLink::SetObjType()
274 |*
275 |*	  Beschreibung
276 *************************************************************************/
277 
SetObjType(sal_uInt16 nObjTypeP)278 void SvBaseLink::SetObjType( sal_uInt16 nObjTypeP )
279 {
280 	DBG_ASSERT( nObjType != OBJECT_CLIENT_DDE, "type already set" );
281 	DBG_ASSERT( !xObj.Is(), "object exist" );
282 
283 	nObjType = nObjTypeP;
284 }
285 
286 /************************************************************************
287 |*	  SvBaseLink::SetName()
288 |*
289 |*	  Beschreibung
290 *************************************************************************/
291 
SetName(const String & rNm)292 void SvBaseLink::SetName( const String & rNm )
293 {
294 	aLinkName = rNm;
295 }
296 
297 /************************************************************************
298 |*	  SvBaseLink::GetName()
299 |*
300 |*	  Beschreibung
301 *************************************************************************/
302 
GetName() const303 String SvBaseLink::GetName() const
304 {
305 	return aLinkName;
306 }
307 
308 /************************************************************************
309 |*	  SvBaseLink::SetObj()
310 |*
311 |*	  Beschreibung
312 *************************************************************************/
313 
SetObj(SvLinkSource * pObj)314 void SvBaseLink::SetObj( SvLinkSource * pObj )
315 {
316 	DBG_ASSERT( (nObjType & OBJECT_CLIENT_SO &&
317 				pImplData->ClientType.bIntrnlLnk) ||
318 				nObjType == OBJECT_CLIENT_GRF,
319 				"no intern link" );
320 	xObj = pObj;
321 }
322 
323 /************************************************************************
324 |*	  SvBaseLink::SetLinkSourceName()
325 |*
326 |*	  Beschreibung
327 *************************************************************************/
328 
SetLinkSourceName(const String & rLnkNm)329 void SvBaseLink::SetLinkSourceName( const String & rLnkNm )
330 {
331 	if( aLinkName == rLnkNm )
332 		return;
333 
334 	AddNextRef(); // sollte ueberfluessig sein
335 	// Alte Verbindung weg
336 	Disconnect();
337 
338 	aLinkName = rLnkNm;
339 
340 	// Neu verbinden
341 	_GetRealObject();
342 	ReleaseRef(); // sollte ueberfluessig sein
343 }
344 
345 /************************************************************************
346 |*	  SvBaseLink::GetLinkSourceName()
347 |*
348 |*	  Beschreibung
349 *************************************************************************/
350 
GetLinkSourceName() const351 String  SvBaseLink::GetLinkSourceName() const
352 {
353 	return aLinkName;
354 }
355 
356 
357 /************************************************************************
358 |*	  SvBaseLink::SetUpdateMode()
359 |*
360 |*	  Beschreibung
361 *************************************************************************/
362 
SetUpdateMode(sal_uInt16 nMode)363 void SvBaseLink::SetUpdateMode( sal_uInt16 nMode )
364 {
365 	if( ( OBJECT_CLIENT_SO & nObjType ) &&
366 		pImplData->ClientType.nUpdateMode != nMode )
367 	{
368 		AddNextRef();
369 		Disconnect();
370 
371 		pImplData->ClientType.nUpdateMode = nMode;
372 		_GetRealObject();
373 		ReleaseRef();
374 	}
375 }
376 
377 // --> OD 2008-06-19 #i88291#
clearStreamToLoadFrom()378 void SvBaseLink::clearStreamToLoadFrom()
379 {
380     m_xInputStreamToLoadFrom.clear();
381     if( xObj.Is() )
382     {
383         xObj->clearStreamToLoadFrom();
384     }
385 }
386 // <--
387 
Update()388 sal_Bool SvBaseLink::Update()
389 {
390 	if( OBJECT_CLIENT_SO & nObjType )
391 	{
392 		AddNextRef();
393 		Disconnect();
394 
395 		_GetRealObject();
396 		ReleaseRef();
397 		if( xObj.Is() )
398 		{
399             xObj->setStreamToLoadFrom(m_xInputStreamToLoadFrom,m_bIsReadOnly);
400             // m_xInputStreamToLoadFrom = 0;
401 			String sMimeType( SotExchange::GetFormatMimeType(
402 							pImplData->ClientType.nCntntType ));
403 			Any aData;
404 
405 			if( xObj->GetData( aData, sMimeType ) )
406 			{
407 				DataChanged( sMimeType, aData );
408 				//JP 13.07.00: Bug 76817 - for manual Updates there is no
409 				//				need to hold the ServerObject
410 				if( OBJECT_CLIENT_DDE == nObjType &&
411 					LINKUPDATE_ONCALL == GetUpdateMode() && xObj.Is() )
412 					xObj->RemoveAllDataAdvise( this );
413 				return sal_True;
414 			}
415 			if( xObj.Is() )
416 			{
417 				// sollten wir asynschron sein?
418 				if( xObj->IsPending() )
419 					return sal_True;
420 
421 				// dann brauchen wir das Object auch nicht mehr
422 				AddNextRef();
423 				Disconnect();
424 				ReleaseRef();
425 			}
426 		}
427 	}
428 	return sal_False;
429 }
430 
431 
GetUpdateMode() const432 sal_uInt16 SvBaseLink::GetUpdateMode() const
433 {
434     return ( OBJECT_CLIENT_SO & nObjType )
435 			? pImplData->ClientType.nUpdateMode
436 			: sal::static_int_cast< sal_uInt16 >( LINKUPDATE_ONCALL );
437 }
438 
439 
_GetRealObject(sal_Bool bConnect)440 void SvBaseLink::_GetRealObject( sal_Bool bConnect)
441 {
442     if(pImpl)
443     {
444         if( !pImpl->m_pLinkMgr )
445 		    return;
446 
447 	    DBG_ASSERT( !xObj.Is(), "object already exist" );
448 
449 	    if( OBJECT_CLIENT_DDE == nObjType )
450 	    {
451 		    String sServer;
452             if( pImpl->m_pLinkMgr->GetDisplayNames( this, &sServer ) &&
453 			    sServer == GetpApp()->GetAppName() )		// interner Link !!!
454 		    {
455 			    // damit der Internal - Link erzeugt werden kann !!!
456 			    nObjType = OBJECT_INTERN;
457                 xObj = pImpl->m_pLinkMgr->CreateObj( this );
458 
459 			    pImplData->ClientType.bIntrnlLnk = sal_True;
460 			    nObjType = OBJECT_CLIENT_DDE;		// damit wir wissen was es mal war !!
461 		    }
462 		    else
463 		    {
464 			    pImplData->ClientType.bIntrnlLnk = sal_False;
465                 xObj = pImpl->m_pLinkMgr->CreateObj( this );
466 		    }
467 	    }
468 	    else if( OBJECT_CLIENT_SO & nObjType )
469             xObj = pImpl->m_pLinkMgr->CreateObj( this );
470 
471         if( bConnect && ( !xObj.Is() || !xObj->Connect( this ) ) )
472 		    Disconnect();
473     }
474     else
475     {
476         OSL_ENSURE(false, "No pImpl (!)");
477     }
478 }
479 
GetContentType() const480 sal_uIntPtr SvBaseLink::GetContentType() const
481 {
482 	if( OBJECT_CLIENT_SO & nObjType )
483 		return pImplData->ClientType.nCntntType;
484 
485 	return 0;		// alle Formate ?
486 }
487 
488 
SetContentType(sal_uIntPtr nType)489 sal_Bool SvBaseLink::SetContentType( sal_uIntPtr nType )
490 {
491 	if( OBJECT_CLIENT_SO & nObjType )
492 	{
493 		pImplData->ClientType.nCntntType = nType;
494 		return sal_True;
495 	}
496 	return sal_False;
497 }
498 
GetLinkManager()499 LinkManager* SvBaseLink::GetLinkManager()
500 {
501     if(pImpl)
502     {
503         return pImpl->m_pLinkMgr;
504     }
505 
506     return 0;
507 }
508 
GetLinkManager() const509 const LinkManager* SvBaseLink::GetLinkManager() const
510 {
511     if(pImpl)
512     {
513         return pImpl->m_pLinkMgr;
514     }
515 
516     return 0;
517 }
518 
SetLinkManager(LinkManager * _pMgr)519 void SvBaseLink::SetLinkManager( LinkManager* _pMgr )
520 {
521     if(pImpl)
522     {
523         pImpl->m_pLinkMgr = _pMgr;
524     }
525     else
526     {
527         OSL_ENSURE(false, "No pImpl (!)");
528     }
529 }
530 
Disconnect()531 void SvBaseLink::Disconnect()
532 {
533 	if( xObj.Is() )
534 	{
535 		xObj->RemoveAllDataAdvise( this );
536 		xObj->RemoveConnectAdvise( this );
537 		xObj.Clear();
538 	}
539 }
540 
DataChanged(const String &,const::com::sun::star::uno::Any &)541 void SvBaseLink::DataChanged( const String &, const ::com::sun::star::uno::Any & )
542 {
543 	switch( nObjType )
544 	{
545 	case OBJECT_DDE_EXTERN:
546 		if( pImplData->DDEType.pItem )
547 			pImplData->DDEType.pItem->Notify();
548 		break;
549 	}
550 }
551 
Edit(Window * pParent,const Link & rEndEditHdl)552 void SvBaseLink::Edit( Window* pParent, const Link& rEndEditHdl )
553 {
554     if(pImpl)
555     {
556         pImpl->m_pParentWin = pParent;
557         pImpl->m_aEndEditLink = rEndEditHdl;
558         pImpl->m_bIsConnect = ( xObj.Is() != sal_False );
559         if( !pImpl->m_bIsConnect )
560 		    _GetRealObject( xObj.Is() );
561 
562         bool bAsync = false;
563         Link aLink = LINK( this, SvBaseLink, EndEditHdl );
564 
565         if( OBJECT_CLIENT_SO & nObjType && pImplData->ClientType.bIntrnlLnk )
566 	    {
567             if( pImpl->m_pLinkMgr )
568 		    {
569                 SvLinkSourceRef ref = pImpl->m_pLinkMgr->CreateObj( this );
570 			    if( ref.Is() )
571                 {
572                     ref->Edit( pParent, this, aLink );
573                     bAsync = true;
574                 }
575 		    }
576 	    }
577 	    else
578         {
579             xObj->Edit( pParent, this, aLink );
580             bAsync = true;
581         }
582 
583         if ( !bAsync )
584         {
585             ExecuteEdit( String() );
586             bWasLastEditOK = sal_False;
587             if ( pImpl->m_aEndEditLink.IsSet() )
588                 pImpl->m_aEndEditLink.Call( this );
589         }
590     }
591     else
592     {
593         OSL_ENSURE(false, "No pImpl (!)");
594     }
595 }
596 
ExecuteEdit(const String & _rNewName)597 bool SvBaseLink::ExecuteEdit( const String& _rNewName )
598 {
599     if(pImpl)
600     {
601         if( _rNewName.Len() != 0 )
602         {
603             SetLinkSourceName( _rNewName );
604             if( !Update() )
605             {
606                 String sApp, sTopic, sItem, sError;
607                 pImpl->m_pLinkMgr->GetDisplayNames( this, &sApp, &sTopic, &sItem );
608                 if( nObjType == OBJECT_CLIENT_DDE )
609                 {
610                     sError = SfxResId( STR_DDE_ERROR );
611 
612                     sal_uInt16 nFndPos = sError.Search( '%' );
613                     if( STRING_NOTFOUND != nFndPos )
614                     {
615                         sError.Erase( nFndPos, 1 ).Insert( sApp, nFndPos );
616                         nFndPos = nFndPos + sApp.Len();
617                     }
618                     if( STRING_NOTFOUND != ( nFndPos = sError.Search( '%', nFndPos )))
619                     {
620                         sError.Erase( nFndPos, 1 ).Insert( sTopic, nFndPos );
621                         nFndPos = nFndPos + sTopic.Len();
622                     }
623                     if( STRING_NOTFOUND != ( nFndPos = sError.Search( '%', nFndPos )))
624                         sError.Erase( nFndPos, 1 ).Insert( sItem, nFndPos );
625                 }
626                 else
627                     return false;
628 
629                 ErrorBox( pImpl->m_pParentWin, WB_OK, sError ).Execute();
630             }
631         }
632         else if( !pImpl->m_bIsConnect )
633             Disconnect();
634         pImpl->m_bIsConnect = false;
635         return true;
636     }
637     else
638     {
639         OSL_ENSURE(false, "No pImpl (!)");
640         return false;
641     }
642 }
643 
Closed()644 void SvBaseLink::Closed()
645 {
646     if( xObj.Is() )
647         // beim Advise Abmelden
648         xObj->RemoveAllDataAdvise( this );
649 }
650 
GetFileDialog(sal_uInt32 nFlags,const String & rFactory) const651 FileDialogHelper* SvBaseLink::GetFileDialog( sal_uInt32 nFlags, const String& rFactory ) const
652 {
653     if(pImpl)
654     {
655         if ( pImpl->m_pFileDlg )
656             delete pImpl->m_pFileDlg;
657         pImpl->m_pFileDlg = new FileDialogHelper( nFlags, rFactory );
658         return pImpl->m_pFileDlg;
659     }
660     else
661     {
662         OSL_ENSURE(false, "No pImpl (!)");
663         return 0;
664     }
665 }
666 
~ImplDdeItem()667 ImplDdeItem::~ImplDdeItem()
668 {
669 	bIsInDTOR = sal_True;
670 	// damit im Disconnect nicht jemand auf die Idee kommt, den Pointer zu
671 	// loeschen!!
672 	SvBaseLinkRef aRef( pLink );
673 	aRef->Disconnect();
674 }
675 
Get(sal_uIntPtr nFormat)676 DdeData* ImplDdeItem::Get( sal_uIntPtr nFormat )
677 {
678 	if( pLink->GetObj() )
679 	{
680 		// ist das noch gueltig?
681 		if( bIsValidData && nFormat == aData.GetFormat() )
682 			return &aData;
683 
684 		Any aValue;
685 		String sMimeType( SotExchange::GetFormatMimeType( nFormat ));
686 		if( pLink->GetObj()->GetData( aValue, sMimeType ) )
687 		{
688 			if( aValue >>= aSeq )
689 			{
690 				aData = DdeData( (const char *)aSeq.getConstArray(), aSeq.getLength(), nFormat );
691 
692 				bIsValidData = sal_True;
693 				return &aData;
694 			}
695 		}
696 	}
697 	aSeq.realloc( 0 );
698 	bIsValidData = sal_False;
699 	return 0;
700 }
701 
702 
Put(const DdeData *)703 sal_Bool ImplDdeItem::Put( const DdeData*  )
704 {
705 	DBG_ERROR( "ImplDdeItem::Put not implemented" );
706 	return sal_False;
707 }
708 
709 
AdviseLoop(sal_Bool bOpen)710 void ImplDdeItem::AdviseLoop( sal_Bool bOpen )
711 {
712 	// Verbindung wird geschlossen, also Link abmelden
713 	if( pLink->GetObj() )
714 	{
715 		if( bOpen )
716 		{
717 			// es wird wieder eine Verbindung hergestellt
718 			if( OBJECT_DDE_EXTERN == pLink->GetObjType() )
719 			{
720 				pLink->GetObj()->AddDataAdvise( pLink, String::CreateFromAscii( "text/plain;charset=utf-16" ),	ADVISEMODE_NODATA );
721 				pLink->GetObj()->AddConnectAdvise( pLink );
722 			}
723 		}
724 		else
725 		{
726 			// damit im Disconnect nicht jemand auf die Idee kommt,
727 			// den Pointer zu loeschen!!
728 			SvBaseLinkRef aRef( pLink );
729 			aRef->Disconnect();
730 		}
731 	}
732 }
733 
734 
FindTopic(const String & rLinkName,sal_uInt16 * pItemStt)735 static DdeTopic* FindTopic( const String & rLinkName, sal_uInt16* pItemStt )
736 {
737 	if( 0 == rLinkName.Len() )
738 		return 0;
739 
740 	String sNm( rLinkName );
741 	sal_uInt16 nTokenPos = 0;
742 	String sService( sNm.GetToken( 0, cTokenSeperator, nTokenPos ) );
743 
744 	DdeServices& rSvc = DdeService::GetServices();
745 	for( DdeService* pService = rSvc.First(); pService;
746 												pService = rSvc.Next() )
747 		if( pService->GetName() == sService )
748 		{
749 			// dann suchen wir uns das Topic
750 			String sTopic( sNm.GetToken( 0, cTokenSeperator, nTokenPos ) );
751 			if( pItemStt )
752 				*pItemStt = nTokenPos;
753 
754 			DdeTopics& rTopics = pService->GetTopics();
755 
756 			for( int i = 0; i < 2; ++i )
757 			{
758 				for( DdeTopic* pTopic = rTopics.First(); pTopic;
759 												pTopic = rTopics.Next() )
760 					if( pTopic->GetName() == sTopic )
761 						return pTopic;
762 
763 				// Topic nicht gefunden ?
764 				// dann versuchen wir ihn mal anzulegen
765 				if( i || !pService->MakeTopic( sTopic ) )
766 					break;	// hat nicht geklappt, also raus
767 			}
768 			break;
769 		}
770 	return 0;
771 }
772 
773 }
774