xref: /trunk/main/svl/source/svdde/ddesvr.cxx (revision c4c57a27)
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_svl.hxx"
26 
27 #define UNICODE
28 #include "ddeimp.hxx"
29 #include <svl/svdde.hxx>
30 #include <svl/svarray.hxx>
31 #include <tools/debug.hxx>
32 #include <osl/thread.h>
33 
34 //static long         hCurConv  = 0;
35 //static DWORD        hDdeInst  = NULL;
36 //static short        nInstance = 0;
37 //static DdeServices* pServices;
38 
39 enum DdeItemType
40 {
41 	DDEITEM,
42 	DDEGETPUTITEM
43 };
44 
45 struct DdeItemImpData
46 {
47 	sal_uLong nHCnv;
48 	sal_uInt16 nCnt;
49 
DdeItemImpDataDdeItemImpData50 	DdeItemImpData( sal_uLong nH ) : nHCnv( nH ), nCnt( 1 ) {}
51 };
52 
53 SV_DECL_VARARR( DdeItemImp, DdeItemImpData, 1, 1 )
SV_IMPL_VARARR(DdeItemImp,DdeItemImpData)54 SV_IMPL_VARARR( DdeItemImp, DdeItemImpData )
55 
56 // --- DdeInternat::SvrCallback() ----------------------------------
57 
58 #ifdef WNT
59 HDDEDATA CALLBACK DdeInternal::SvrCallback(
60 			WORD nCode, WORD nCbType, HCONV hConv, HSZ hText1, HSZ hText2,
61 			HDDEDATA hData, DWORD, DWORD )
62 #else
63 #if defined ( MTW ) || ( defined ( GCC ) && defined ( OS2 )) || defined( ICC )
64 HDDEDATA CALLBACK __EXPORT DdeInternal::SvrCallback(
65 			WORD nCode, WORD nCbType, HCONV hConv, HSZ hText1, HSZ hText2,
66 			HDDEDATA hData, DWORD, DWORD )
67 #else
68 HDDEDATA CALLBACK _export DdeInternal::SvrCallback(
69 			WORD nCode, WORD nCbType, HCONV hConv, HSZ hText1, HSZ hText2,
70 			HDDEDATA hData, DWORD, DWORD )
71 #endif
72 #endif
73 {
74 	DdeServices&    rAll = DdeService::GetServices();
75 	DdeService*     pService;
76 	DdeTopic*       pTopic;
77 	DdeItem*        pItem;
78 	DdeData*        pData;
79 	Conversation*   pC;
80 
81 	DdeInstData* pInst = ImpGetInstData();
82 	DBG_ASSERT(pInst,"SVDDE:No instance data");
83 
84 	switch( nCode )
85 	{
86 		case XTYP_WILDCONNECT:
87 		{
88 			int nTopics = 0;
89 
90 #if 1
91 			TCHAR chTopicBuf[250];
92 			if( hText1 )
93 				DdeQueryString( pInst->hDdeInstSvr, hText1, chTopicBuf,
94 								sizeof(chTopicBuf)/sizeof(TCHAR), CP_WINUNICODE );
95 
96 			for( pService = rAll.First();pService;pService = rAll.Next() )
97 			{
98 				if ( !hText2 || ( *pService->pName == hText2 ) )
99 				{
100 					String sTopics( pService->Topics() );
101 					if( sTopics.Len() )
102 					{
103 						if( hText1 )
104 						{
105 							sal_uInt16 n = 0;
106 							while( STRING_NOTFOUND != n )
107 							{
108 								String s( sTopics.GetToken( 0, '\t', n ));
109 								if( s == reinterpret_cast<const sal_Unicode*>(chTopicBuf) )
110 									++nTopics;
111 							}
112 						}
113 						else
114 							nTopics += sTopics.GetTokenCount( '\t' );
115 					}
116 				}
117 			}
118 
119 #else
120 			for( pService = rAll.First();pService;pService = rAll.Next() )
121 			{
122 				if ( !hText2 || ( *pService->pName == hText2 ) )
123 				{
124 					for( pTopic = pService->aTopics.First(); pTopic;
125 						 pTopic = pService->aTopics.Next() )
126 					{
127 						if ( !hText1 || (*pTopic->pName == hText1) )
128 							nTopics++;
129 					}
130 				}
131 			}
132 #endif
133 			if( !nTopics )
134 				return (HDDEDATA)NULL;
135 
136 			HSZPAIR* pPairs = new HSZPAIR [nTopics + 1];
137 			if ( !pPairs )
138 				return (HDDEDATA)NULL;
139 
140 			HSZPAIR* q = pPairs;
141 			for( pService = rAll.First(); pService; pService = rAll.Next() )
142 			{
143 				if ( !hText2 || (*pService->pName == hText2 ) )
144 				{
145 #if 0
146 					for ( pTopic = pService->aTopics.First(); pTopic;
147 						  pTopic = pService->aTopics.Next() )
148 					{
149 						if ( !hText1 || (*pTopic->pName == hText1) )
150 						{
151 							q->hszSvc   = *pService->pName;
152 							q->hszTopic = *pTopic->pName;
153 							q++;
154 						}
155 					}
156 #else
157 					String sTopics( pService->Topics() );
158 					sal_uInt16 n = 0;
159 					while( STRING_NOTFOUND != n )
160 					{
161 						String s( sTopics.GetToken( 0, '\t', n ));
162 						s.EraseAllChars( '\n' ).EraseAllChars( '\r' );
163 						if( !hText1 || s == reinterpret_cast<const sal_Unicode*>(chTopicBuf) )
164 						{
165 							DdeString aDStr( pInst->hDdeInstSvr, s );
166 							pTopic = FindTopic( *pService, (HSZ)aDStr );
167 							if( pTopic )
168 							{
169 								q->hszSvc   = *pService->pName;
170 								q->hszTopic = *pTopic->pName;
171 								q++;
172 							}
173 						}
174 					}
175 
176 #endif
177 				}
178 			}
179 
180 			q->hszSvc   = NULL;
181 			q->hszTopic = NULL;
182 			HDDEDATA h = DdeCreateDataHandle(
183 							pInst->hDdeInstSvr, (LPBYTE) pPairs,
184 							sizeof(HSZPAIR) * (nTopics+1),
185 							0, NULL, nCbType, 0);
186 			delete [] pPairs;
187 			return h;
188 		}
189 
190 		case XTYP_CONNECT:
191 			pService = FindService( hText2 );
192 			if ( pService)
193 				pTopic = FindTopic( *pService, hText1 );
194 			else
195 				pTopic = NULL;
196 			if ( pTopic )
197 				return (HDDEDATA)DDE_FACK;
198 			else
199 				return (HDDEDATA) NULL;
200 
201 		case XTYP_CONNECT_CONFIRM:
202 			pService = FindService( hText2 );
203 			if ( pService )
204 			{
205 				pTopic = FindTopic( *pService, hText1 );
206 				if ( pTopic )
207 				{
208 					pTopic->Connect( (long) hConv );
209 					pC = new Conversation;
210 					pC->hConv = hConv;
211 					pC->pTopic = pTopic;
212 					pService->pConv->Insert( pC );
213 				}
214 			}
215 			return (HDDEDATA)NULL;
216 	}
217 
218 	for ( pService = rAll.First(); pService; pService = rAll.Next() )
219 	{
220 		for( pC = pService->pConv->First(); pC;
221 			 pC = pService->pConv->Next() )
222 		{
223 			if ( pC->hConv == hConv )
224 				goto found;
225 		}
226 	}
227 
228 	return (HDDEDATA) DDE_FNOTPROCESSED;
229 
230 found:
231 	if ( nCode == XTYP_DISCONNECT)
232 	{
233 		pC->pTopic->_Disconnect( (long) hConv );
234 		pService->pConv->Remove( pC );
235 		delete pC;
236 		return (HDDEDATA)NULL;
237 	}
238 
239 	sal_Bool bExec = sal_Bool(nCode == XTYP_EXECUTE);
240 	pTopic = pC->pTopic;
241 	if ( pTopic && !bExec )
242 		pItem = FindItem( *pTopic, hText2 );
243 	else
244 		pItem = NULL;
245 
246 	if ( !bExec && !pService->HasCbFormat( nCbType ) )
247 		pItem = NULL;
248 	if ( !pItem && !bExec )
249 		return (HDDEDATA)DDE_FNOTPROCESSED;
250 	if ( pItem )
251 		pTopic->aItem = pItem->GetName();
252 	else
253 		pTopic->aItem.Erase();
254 
255 	sal_Bool bRes = sal_False;
256 	pInst->hCurConvSvr = hConv;
257 	switch( nCode )
258 	{
259 		case XTYP_REQUEST:
260 		case XTYP_ADVREQ:
261 			{
262 			String aRes;          // darf erst am Ende freigegeben werden!!
263 			if ( pTopic->IsSystemTopic() )
264 			{
265 				if ( pTopic->aItem == reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_TOPICS) )
266 					aRes = pService->Topics();
267 				else if ( pTopic->aItem == reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_SYSITEMS) )
268 					aRes = pService->SysItems();
269 				else if ( pTopic->aItem == reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_STATUS) )
270 					aRes = pService->Status();
271 				else if ( pTopic->aItem == reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_FORMATS) )
272 					aRes = pService->Formats();
273 				else if ( pTopic->aItem ==  reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_HELP) )
274 					aRes = pService->GetHelp();
275 				else
276 					aRes = pService->SysTopicGet( pTopic->aItem );
277 
278 				if ( aRes.Len() )
279 					pData = new DdeData( aRes );
280 				else
281 					pData = NULL;
282 			}
283 			else if( DDEGETPUTITEM == pItem->nType )
284 				pData = ((DdeGetPutItem*)pItem)->Get(
285 							DdeData::GetInternalFormat( nCbType ) );
286 			else
287 				pData = pTopic->Get( DdeData::GetInternalFormat( nCbType ));
288 
289 			if ( pData )
290 				return DdeCreateDataHandle( pInst->hDdeInstSvr,
291 											(LPBYTE)pData->pImp->pData,
292 											pData->pImp->nData,
293 											0, hText2,
294 											DdeData::GetExternalFormat(
295 												pData->pImp->nFmt ),
296 											0 );
297 			}
298 			break;
299 
300 		case XTYP_POKE:
301 			if ( !pTopic->IsSystemTopic() )
302 			{
303 				DdeData d;
304 				d.pImp->hData = hData;
305 				d.pImp->nFmt  = DdeData::GetInternalFormat( nCbType );
306 				d.Lock();
307 				if( DDEGETPUTITEM == pItem->nType )
308 					bRes = ((DdeGetPutItem*)pItem)->Put( &d );
309 				else
310 					bRes = pTopic->Put( &d );
311 			}
312 			pInst->hCurConvSvr = NULL;
313 			if ( bRes )
314 				return (HDDEDATA)DDE_FACK;
315 			else
316 				return (HDDEDATA) DDE_FNOTPROCESSED;
317 
318 		case XTYP_ADVSTART:
319 			{
320 				// wird das Item zum erstenmal ein HotLink ?
321 				if( !pItem->pImpData && pTopic->StartAdviseLoop() )
322 				{
323 					// dann wurde das Item ausgewechselt
324 					pTopic->aItems.Remove( pItem );
325 					DdeItem* pTmp;
326 					for(  pTmp = pTopic->aItems.First(); pTmp;
327 									pTmp = pTopic->aItems.Next() )
328 						if( *pTmp->pName == hText2 )
329 						{
330 							// es wurde tatsaechlich ausgewechselt
331 							delete pItem;
332 							pItem = 0;
333 							break;
334 						}
335 					if( pItem )
336 						// es wurde doch nicht ausgewechselt, also wieder rein
337 						pTopic->aItems.Insert( pItem );
338 					else
339 						pItem = pTmp;
340 				}
341 				pItem->IncMonitor( (long)hConv );
342 				pInst->hCurConvSvr = NULL;
343 			}
344 			return (HDDEDATA)sal_True;
345 
346 		case XTYP_ADVSTOP:
347 			pItem->DecMonitor( (long)hConv );
348 			if( !pItem->pImpData )
349 				pTopic->StopAdviseLoop();
350 			pInst->hCurConvSvr = NULL;
351 			return (HDDEDATA)sal_True;
352 
353 		case XTYP_EXECUTE:
354 			{
355 				DdeData aExec;
356 				aExec.pImp->hData = hData;
357 				aExec.pImp->nFmt  = DdeData::GetInternalFormat( nCbType );
358 				aExec.Lock();
359 				String aName;
360 
361 				aName = (const sal_Unicode *)aExec.pImp->pData;
362 
363 				if( pTopic->IsSystemTopic() )
364 					bRes = pService->SysTopicExecute( &aName );
365 				else
366 					bRes = pTopic->Execute( &aName );
367 			}
368 			pInst->hCurConvSvr = NULL;
369 			if ( bRes )
370 				return (HDDEDATA)DDE_FACK;
371 			else
372 				return (HDDEDATA)DDE_FNOTPROCESSED;
373 	}
374 
375 	return (HDDEDATA)NULL;
376 }
377 
378 // --- DdeInternat::FindService() ----------------------------------
379 
FindService(HSZ hService)380 DdeService* DdeInternal::FindService( HSZ hService )
381 {
382 	DdeService*  s;
383 	DdeServices& rSvc = DdeService::GetServices();
384 	for ( s = rSvc.First(); s; s = rSvc.Next() )
385 	{
386 		if ( *s->pName == hService )
387 			return s;
388 	}
389 
390 	return NULL;
391 }
392 
393 // --- DdeInternat::FindTopic() ------------------------------------
394 
FindTopic(DdeService & rService,HSZ hTopic)395 DdeTopic* DdeInternal::FindTopic( DdeService& rService, HSZ hTopic )
396 {
397 	DdeTopic* s;
398 	DdeTopics& rTopics = rService.aTopics;
399 	int bWeiter = sal_False;
400 	DdeInstData* pInst = ImpGetInstData();
401 	DBG_ASSERT(pInst,"SVDDE:No instance data");
402 
403 	do {            // middle check loop
404 		for ( s = rTopics.First(); s; s = rTopics.Next() )
405 		{
406 			if ( *s->pName == hTopic )
407 				return s;
408 		}
409 
410 		bWeiter = !bWeiter;
411 		if( !bWeiter )
412 			break;
413 
414 		// dann befragen wir doch mal unsere Ableitung:
415 		TCHAR chBuf[250];
416 		DdeQueryString(pInst->hDdeInstSvr,hTopic,chBuf,sizeof(chBuf)/sizeof(TCHAR),CP_WINUNICODE );
417 		bWeiter = rService.MakeTopic( reinterpret_cast<const sal_Unicode*>(chBuf) );
418 		// dann muessen wir noch mal suchen
419 	} while( bWeiter );
420 
421 	return 0;
422 }
423 
424 // --- DdeInternal::FindItem() -------------------------------------
425 
FindItem(DdeTopic & rTopic,HSZ hItem)426 DdeItem* DdeInternal::FindItem( DdeTopic& rTopic, HSZ hItem )
427 {
428 	DdeItem* s;
429 	DdeItems& rItems = rTopic.aItems;
430 	DdeInstData* pInst = ImpGetInstData();
431 	DBG_ASSERT(pInst,"SVDDE:No instance data");
432 	int bWeiter = sal_False;
433 
434 	do {            // middle check loop
435 
436 		for ( s = rItems.First(); s; s = rItems.Next() )
437 			if ( *s->pName == hItem )
438 				return s;
439 
440 		bWeiter = !bWeiter;
441 		if( !bWeiter )
442 			break;
443 
444 		// dann befragen wir doch mal unsere Ableitung:
445 		TCHAR chBuf[250];
446 		DdeQueryString(pInst->hDdeInstSvr,hItem,chBuf,sizeof(chBuf)/sizeof(TCHAR),CP_WINUNICODE );
447 		bWeiter = rTopic.MakeItem( reinterpret_cast<const sal_Unicode*>(chBuf) );
448 		// dann muessen wir noch mal suchen
449 	} while( bWeiter );
450 
451 	return 0;
452 }
453 
454 // --- DdeService::DdeService() ------------------------------------
455 
DdeService(const String & rService)456 DdeService::DdeService( const String& rService )
457 {
458 	DdeInstData* pInst = ImpGetInstData();
459 	if( !pInst )
460 		pInst = ImpInitInstData();
461 	pInst->nRefCount++;
462 	pInst->nInstanceSvr++;
463 
464 	if ( !pInst->hDdeInstSvr )
465 	{
466 		nStatus = sal::static_int_cast< short >(
467             DdeInitialize( &pInst->hDdeInstSvr,
468                            (PFNCALLBACK)DdeInternal::SvrCallback,
469                            APPCLASS_STANDARD |
470                            CBF_SKIP_REGISTRATIONS |
471                            CBF_SKIP_UNREGISTRATIONS, 0L ) );
472 		pInst->pServicesSvr = new DdeServices;
473 	}
474 	else
475 		nStatus = DMLERR_NO_ERROR;
476 
477 	pConv = new ConvList;
478 
479 	if ( pInst->pServicesSvr )
480 		pInst->pServicesSvr->Insert( this );
481 
482 	pName = new DdeString( pInst->hDdeInstSvr, rService );
483 	if ( nStatus == DMLERR_NO_ERROR )
484 		if ( !DdeNameService( pInst->hDdeInstSvr, *pName, NULL,
485 								DNS_REGISTER | DNS_FILTEROFF ) )
486 			nStatus = DMLERR_SYS_ERROR;
487 
488 	AddFormat( FORMAT_STRING );
489 	pSysTopic = new DdeTopic( reinterpret_cast<const sal_Unicode*>(SZDDESYS_TOPIC) );
490 	pSysTopic->AddItem( DdeItem( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_TOPICS) ) );
491 	pSysTopic->AddItem( DdeItem( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_SYSITEMS) ) );
492 	pSysTopic->AddItem( DdeItem( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_STATUS) ) );
493 	pSysTopic->AddItem( DdeItem( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_FORMATS) ) );
494 	pSysTopic->AddItem( DdeItem( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_HELP) ) );
495 	AddTopic( *pSysTopic );
496 }
497 
498 // --- DdeService::~DdeService() -----------------------------------
499 
~DdeService()500 DdeService::~DdeService()
501 {
502 	DdeInstData* pInst = ImpGetInstData();
503 	DBG_ASSERT(pInst,"SVDDE:No instance data");
504 	if ( pInst->pServicesSvr )
505 		pInst->pServicesSvr->Remove( this );
506 
507 	// MT: Im Auftrage des Herrn (AM) auskommentiert...
508 	// Grund:
509 	// Bei Client/Server werden die Server nicht beendet, wenn mehr
510 	// als einer gestartet.
511 	// Weil keine System-Messagequeue ?!
512 
513 	delete pSysTopic;
514 	delete pName;
515 
516 	pInst->nInstanceSvr--;
517 	pInst->nRefCount--;
518 	if ( !pInst->nInstanceSvr && pInst->hDdeInstSvr )
519 	{
520 		if( DdeUninitialize( pInst->hDdeInstSvr ) )
521 		{
522 			pInst->hDdeInstSvr = NULL;
523 			delete pInst->pServicesSvr;
524 			pInst->pServicesSvr = NULL;
525 			if( pInst->nRefCount == 0)
526 				ImpDeinitInstData();
527 		}
528 	}
529 	delete pConv;
530 }
531 
532 // --- DdeService::GetName() ---------------------------------------
533 
GetName() const534 const String& DdeService::GetName() const
535 {
536 	return *pName;
537 }
538 
539 // --- DdeService::GetServices() -----------------------------------
540 
GetServices()541 DdeServices& DdeService::GetServices()
542 {
543 	DdeInstData* pInst = ImpGetInstData();
544 	DBG_ASSERT(pInst,"SVDDE:No instance data");
545 	return *(pInst->pServicesSvr);
546 }
547 
548 // --- DdeService::AddTopic() --------------------------------------
549 
AddTopic(const DdeTopic & rTopic)550 void DdeService::AddTopic( const DdeTopic& rTopic )
551 {
552 	RemoveTopic( rTopic );
553 	aTopics.Insert( (DdeTopic*) &rTopic );
554 }
555 
556 // --- DdeService::RemoveTopic() -----------------------------------
557 
RemoveTopic(const DdeTopic & rTopic)558 void DdeService::RemoveTopic( const DdeTopic& rTopic )
559 {
560 	DdeTopic* t;
561 	for ( t = aTopics.First(); t; t = aTopics.Next() )
562 	{
563 		if ( !DdeCmpStringHandles (*t->pName, *rTopic.pName ) )
564 		{
565 			aTopics.Remove( t );
566 			// JP 27.07.95: und alle Conversions loeschen !!!
567 			//              (sonst wird auf geloeschten Topics gearbeitet!!)
568 			for( sal_uLong n = pConv->Count(); n; )
569 			{
570 				Conversation* pC = pConv->GetObject( --n );
571 				if( pC->pTopic == &rTopic )
572 				{
573 					pConv->Remove( pC );
574 					delete pC;
575 				}
576 			}
577 			break;
578 		}
579 	}
580 }
581 
582 // --- DdeService::HasCbFormat() -----------------------------------
583 
HasCbFormat(sal_uInt16 nFmt)584 sal_Bool DdeService::HasCbFormat( sal_uInt16 nFmt )
585 {
586 	return sal_Bool( aFormats.GetPos( nFmt ) != LIST_ENTRY_NOTFOUND );
587 }
588 
589 // --- DdeService::HasFormat() -------------------------------------
590 
HasFormat(sal_uLong nFmt)591 sal_Bool DdeService::HasFormat( sal_uLong nFmt )
592 {
593 	return HasCbFormat( (sal_uInt16)DdeData::GetExternalFormat( nFmt ));
594 }
595 
596 // --- DdeService::AddFormat() -------------------------------------
597 
AddFormat(sal_uLong nFmt)598 void DdeService::AddFormat( sal_uLong nFmt )
599 {
600 	nFmt = DdeData::GetExternalFormat( nFmt );
601 	aFormats.Remove( nFmt );
602 	aFormats.Insert( nFmt );
603 }
604 
605 // --- DdeService::RemoveFormat() ----------------------------------
606 
RemoveFormat(sal_uLong nFmt)607 void DdeService::RemoveFormat( sal_uLong nFmt )
608 {
609 	aFormats.Remove( DdeData::GetExternalFormat( nFmt ) );
610 }
611 
612 // --- DdeTopic::DdeTopic() ----------------------------------------
613 
DdeTopic(const String & rName)614 DdeTopic::DdeTopic( const String& rName )
615 {
616 	DdeInstData* pInst = ImpGetInstData();
617 	DBG_ASSERT(pInst,"SVDDE:No instance data");
618 	pName = new DdeString( pInst->hDdeInstSvr, rName );
619 }
620 
621 // --- DdeTopic::~DdeTopic() ---------------------------------------
622 
~DdeTopic()623 DdeTopic::~DdeTopic()
624 {
625 	DdeItem* t;
626 	while( ( t = aItems.First() ) != NULL )
627 	{
628 		aItems.Remove( t );
629 		t->pMyTopic = 0;
630 		delete t;
631 	}
632 	delete pName;
633 }
634 
635 // --- DdeTopic::GetName() -----------------------------------------
636 
GetName() const637 const String& DdeTopic::GetName() const
638 {
639 	return *pName;
640 }
641 
642 // --- DdeTopic::IsSystemTopic() -----------------------------------
643 
IsSystemTopic()644 sal_Bool DdeTopic::IsSystemTopic()
645 {
646 	return sal_Bool (GetName() == reinterpret_cast<const sal_Unicode*>(SZDDESYS_TOPIC));
647 }
648 
649 // --- DdeTopic::AddItem() -----------------------------------------
650 
AddItem(const DdeItem & r)651 DdeItem* DdeTopic::AddItem( const DdeItem& r )
652 {
653 	DdeItem* s;
654 	if( DDEGETPUTITEM == r.nType )
655 		s = new DdeGetPutItem( r );
656 	else
657 		s = new DdeItem( r );
658 	if ( s )
659 	{
660 		aItems.Insert( s );
661 		s->pMyTopic = this;
662 	}
663 	return s;
664 }
665 
666 // --- DdeTopic::InsertItem() -----------------------------------------
667 
InsertItem(DdeItem * pNew)668 void DdeTopic::InsertItem( DdeItem* pNew )
669 {
670 	if( pNew )
671 	{
672 		aItems.Insert( pNew );
673 		pNew->pMyTopic = this;
674 	}
675 }
676 
677 // --- DdeTopic::RemoveItem() --------------------------------------
678 
RemoveItem(const DdeItem & r)679 void DdeTopic::RemoveItem( const DdeItem& r )
680 {
681 	DdeItem* s;
682 	for ( s = aItems.First(); s; s = aItems.Next() )
683 	{
684 		if ( !DdeCmpStringHandles (*s->pName, *r.pName ) )
685 			break;
686 	}
687 
688 	if ( s )
689 	{
690 		aItems.Remove( s );
691 		s->pMyTopic = 0;
692 		delete s;
693 	}
694 }
695 
696 // --- DdeTopic::NotifyClient() ------------------------------------
697 
NotifyClient(const String & rItem)698 void DdeTopic::NotifyClient( const String& rItem )
699 {
700 	DdeItem* pItem;
701 	DdeInstData* pInst = ImpGetInstData();
702 	DBG_ASSERT(pInst,"SVDDE:No instance data");
703 	for ( pItem = aItems.First(); pItem; pItem = aItems.Next() )
704 	{
705 		if ( pItem->GetName() == rItem )
706 		{
707 			if ( pItem->pImpData )
708 				DdePostAdvise( pInst->hDdeInstSvr, *pName, *pItem->pName );
709 		}
710 		break;
711 	}
712 }
713 
714 // --- DdeTopic::Connect() -----------------------------------------
715 
Connect(long nId)716 void __EXPORT DdeTopic::Connect( long nId )
717 {
718 	aConnectLink.Call( (void*)nId );
719 }
720 
721 // --- DdeTopic::Disconnect() --------------------------------------
722 
Disconnect(long nId)723 void __EXPORT DdeTopic::Disconnect( long nId )
724 {
725 	aDisconnectLink.Call( (void*)nId );
726 }
727 
728 // --- DdeTopic::_Disconnect() --------------------------------------
729 
_Disconnect(long nId)730 void __EXPORT DdeTopic::_Disconnect( long nId )
731 {
732 	for( DdeItem* pItem = aItems.First(); pItem; pItem = aItems.Next() )
733 		pItem->DecMonitor( nId );
734 
735 	Disconnect( nId );
736 }
737 
738 // --- DdeTopic::Get() ---------------------------------------------
739 
Get(sal_uLong nFmt)740 DdeData* __EXPORT DdeTopic::Get( sal_uLong nFmt )
741 {
742 	if ( aGetLink.IsSet() )
743 		return (DdeData*)aGetLink.Call( (void*)nFmt );
744 	else
745 		return NULL;
746 }
747 
748 // --- DdeTopic::Put() ---------------------------------------------
749 
Put(const DdeData * r)750 sal_Bool __EXPORT DdeTopic::Put( const DdeData* r )
751 {
752 	if ( aPutLink.IsSet() )
753 		return (sal_Bool)aPutLink.Call( (void*) r );
754 	else
755 		return sal_False;
756 }
757 
758 // --- DdeTopic::Execute() -----------------------------------------
759 
Execute(const String * r)760 sal_Bool __EXPORT DdeTopic::Execute( const String* r )
761 {
762 	if ( aExecLink.IsSet() )
763 		return (sal_Bool)aExecLink.Call( (void*)r );
764 	else
765 		return sal_False;
766 }
767 
768 // --- DdeTopic::GetConvId() ---------------------------------------
769 
GetConvId()770 sal_uIntPtr DdeTopic::GetConvId()
771 {
772 	DdeInstData* pInst = ImpGetInstData();
773 	DBG_ASSERT(pInst,"SVDDE:No instance data");
774 	return (sal_uIntPtr)pInst->hCurConvSvr;
775 }
776 
777 // --- DdeTopic::StartAdviseLoop() ---------------------------------
778 
StartAdviseLoop()779 sal_Bool DdeTopic::StartAdviseLoop()
780 {
781 	return sal_False;
782 }
783 
784 // --- DdeTopic::StopAdviseLoop() ----------------------------------
785 
StopAdviseLoop()786 sal_Bool DdeTopic::StopAdviseLoop()
787 {
788 	return sal_False;
789 }
790 
791 // --- DdeItem::DdeItem() ------------------------------------------
792 
DdeItem(const sal_Unicode * p)793 DdeItem::DdeItem( const sal_Unicode* p )
794 {
795 	DdeInstData* pInst = ImpGetInstData();
796 	DBG_ASSERT(pInst,"SVDDE:No instance data");
797 	pName = new DdeString( pInst->hDdeInstSvr, p );
798 	nType = DDEITEM;
799 	pMyTopic = 0;
800 	pImpData = 0;
801 }
802 
803 // --- DdeItem::DdeItem() ------------------------------------------
804 
DdeItem(const String & r)805 DdeItem::DdeItem( const String& r)
806 {
807 	DdeInstData* pInst = ImpGetInstData();
808 	DBG_ASSERT(pInst,"SVDDE:No instance data");
809 	pName = new DdeString( pInst->hDdeInstSvr, r );
810 	nType = DDEITEM;
811 	pMyTopic = 0;
812 	pImpData = 0;
813 }
814 
815 // --- DdeItem::DdeItem() ------------------------------------------
816 
DdeItem(const DdeItem & r)817 DdeItem::DdeItem( const DdeItem& r)
818 {
819 	DdeInstData* pInst = ImpGetInstData();
820 	DBG_ASSERT(pInst,"SVDDE:No instance data");
821 	pName = new DdeString( pInst->hDdeInstSvr, *r.pName );
822 	nType = DDEITEM;
823 	pMyTopic = 0;
824 	pImpData = 0;
825 }
826 
827 // --- DdeItem::~DdeItem() -----------------------------------------
828 
~DdeItem()829 DdeItem::~DdeItem()
830 {
831 	if( pMyTopic )
832 		pMyTopic->aItems.Remove( this );
833 	delete pName;
834 	delete pImpData;
835 }
836 
837 // --- DdeItem::GetName() ------------------------------------------
838 
GetName() const839 const String& DdeItem::GetName() const
840 {
841 	return *pName;
842 }
843 
844 // --- DdeItem::NotifyClient() ------------------------------------------
845 
NotifyClient()846 void DdeItem::NotifyClient()
847 {
848 	if( pMyTopic && pImpData )
849 	{
850 		DdeInstData* pInst = ImpGetInstData();
851 		DBG_ASSERT(pInst,"SVDDE:No instance data");
852 		DdePostAdvise( pInst->hDdeInstSvr, *pMyTopic->pName, *pName );
853 	}
854 }
855 
856 // --- DdeItem::IncMonitor() ------------------------------------------
857 
IncMonitor(sal_uLong nHCnv)858 void DdeItem::IncMonitor( sal_uLong nHCnv )
859 {
860 	if( !pImpData )
861 	{
862 		pImpData = new DdeItemImp;
863 		if( DDEGETPUTITEM == nType )
864 			((DdeGetPutItem*)this)->AdviseLoop( sal_True );
865 	}
866 	else
867 	{
868 		for( sal_uInt16 n = pImpData->Count(); n; )
869 			if( (*pImpData)[ --n ].nHCnv == nHCnv )
870 			{
871 				++(*pImpData)[ n ].nHCnv;
872 				return ;
873 			}
874 	}
875 
876 	pImpData->Insert( DdeItemImpData( nHCnv ), pImpData->Count() );
877 }
878 
879 // --- DdeItem::DecMonitor() ------------------------------------------
880 
DecMonitor(sal_uLong nHCnv)881 void DdeItem::DecMonitor( sal_uLong nHCnv )
882 {
883 	if( pImpData )
884 	{
885 		DdeItemImpData* pData = (DdeItemImpData*)pImpData->GetData();
886 		for( sal_uInt16 n = pImpData->Count(); n; --n, ++pData )
887 			if( pData->nHCnv == nHCnv )
888 			{
889 				if( !pData->nCnt || !--pData->nCnt )
890 				{
891 					if( 1 < pImpData->Count() )
892 						pImpData->Remove( pImpData->Count() - n );
893 					else
894 					{
895 						delete pImpData, pImpData = 0;
896 						if( DDEGETPUTITEM == nType )
897 							((DdeGetPutItem*)this)->AdviseLoop( sal_False );
898 					}
899 				}
900 				return ;
901 			}
902 	}
903 }
904 
905 // --- DdeItem::GetLinks() ------------------------------------------
906 
GetLinks()907 short DdeItem::GetLinks()
908 {
909 	short nCnt = 0;
910 	if( pImpData )
911 		for( sal_uInt16 n = pImpData->Count(); n; )
912 			nCnt = nCnt + (*pImpData)[ --n ].nCnt;
913 	return nCnt;
914 }
915 
916 // --- DdeGetPutItem::DdeGetPutItem() ------------------------------
917 
DdeGetPutItem(const sal_Unicode * p)918 DdeGetPutItem::DdeGetPutItem( const sal_Unicode* p )
919 	: DdeItem( p )
920 {
921 	nType = DDEGETPUTITEM;
922 }
923 
924 // --- DdeGetPutItem::DdeGetPutItem() ------------------------------
925 
DdeGetPutItem(const String & rStr)926 DdeGetPutItem::DdeGetPutItem( const String& rStr )
927 	: DdeItem( rStr )
928 {
929 	nType = DDEGETPUTITEM;
930 }
931 
932 // --- DdeGetPutItem::DdeGetPutItem() ------------------------------
933 
DdeGetPutItem(const DdeItem & rItem)934 DdeGetPutItem::DdeGetPutItem( const DdeItem& rItem )
935 	: DdeItem( rItem )
936 {
937 	nType = DDEGETPUTITEM;
938 }
939 
940 
941 // --- DdeGetPutData::Get() ----------------------------------------
942 
Get(sal_uLong)943 DdeData* DdeGetPutItem::Get( sal_uLong )
944 {
945 	return 0;
946 }
947 
948 // --- DdeGetPutData::Put() ----------------------------------------
949 
Put(const DdeData *)950 sal_Bool DdeGetPutItem::Put( const DdeData* )
951 {
952 	return sal_False;
953 }
954 
955 // --- DdeGetPutData::AdviseLoop() ---------------------------------
956 
AdviseLoop(sal_Bool)957 void DdeGetPutItem::AdviseLoop( sal_Bool )
958 {
959 }
960 
961 
962 // --- DdeService::SysItems() --------------------------------------
963 
SysItems()964 String DdeService::SysItems()
965 {
966 	String s;
967 	DdeTopic* t;
968 	for ( t = aTopics.First(); t; t = aTopics.Next() )
969 	{
970 		if ( t->GetName() == reinterpret_cast<const sal_Unicode*>(SZDDESYS_TOPIC) )
971 		{
972 			short n = 0;
973 			DdeItem* pi;
974 			for ( pi = t->aItems.First(); pi; pi = t->aItems.Next(), n++ )
975 			{
976 				if ( n )
977 					s += '\t';
978 				s += pi->GetName();
979 			}
980 			s += String::CreateFromAscii("\r\n");
981 		}
982 	}
983 
984 	return s;
985 }
986 
987 // --- DdeService::Topics() ----------------------------------------
988 
Topics()989 String DdeService::Topics()
990 {
991 	String      s;
992 	DdeTopic*   t;
993 	short       n = 0;
994 
995 	for ( t = aTopics.First(); t; t = aTopics.Next(), n++ )
996 	{
997 		if ( n )
998 			s += '\t';
999 		s += t->GetName();
1000 	}
1001 	s += String::CreateFromAscii("\r\n");
1002 
1003 	return s;
1004 }
1005 
1006 // --- DdeService::Formats() ---------------------------------------
1007 
Formats()1008 String DdeService::Formats()
1009 {
1010 	String      s;
1011 	long        f;
1012 	TCHAR       buf[128];
1013 	LPCTSTR		p;
1014 	short       n = 0;
1015 
1016 	for ( f = aFormats.First(); f; f = aFormats.Next(), n++ )
1017 	{
1018 		if ( n )
1019 			s += '\t';
1020 		p = buf;
1021 
1022 		switch( (sal_uInt16)f )
1023 		{
1024 			case CF_TEXT:
1025 				p = reinterpret_cast<LPCTSTR>(String::CreateFromAscii("TEXT").GetBuffer());
1026 				break;
1027 			case CF_BITMAP:
1028 				p = reinterpret_cast<LPCTSTR>(String::CreateFromAscii("BITMAP").GetBuffer());
1029 				break;
1030 #ifdef OS2
1031 			case CF_DSPTEXT:
1032 				p = String::CreateFromAscii("TEXT").GetBuffer();
1033 				break;
1034 			case CF_DSPBITMAP:
1035 				p = String::CreateFromAscii("BITMAP").GetBuffer();
1036 				break;
1037 			case CF_METAFILE:
1038 				p = String::CreateFromAscii("METAFILE").GetBuffer();
1039 				break;
1040 			case CF_DSPMETAFILE:
1041 				p = String::CreateFromAscii("METAFILE").GetBuffer();
1042 				break;
1043 			case CF_PALETTE:
1044 				p = String::CreateFromAscii("PALETTE").GetBuffer();
1045 				break;
1046 			default:
1047 				p= String::CreateFromAscii("PRIVATE").GetBuffer();
1048 #else
1049 			default:
1050 				GetClipboardFormatName( (UINT)f, buf, sizeof(buf) / sizeof(TCHAR) );
1051 #endif
1052 		}
1053 		s += String( reinterpret_cast<const sal_Unicode*>(p) );
1054 	}
1055 	s += String::CreateFromAscii("\r\n");
1056 
1057 	return s;
1058 }
1059 
1060 // --- DdeService::Status() ----------------------------------------
1061 
Status()1062 String DdeService::Status()
1063 {
1064 	return IsBusy() ? String::CreateFromAscii("Busy\r\n") : String::CreateFromAscii("Ready\r\n");
1065 }
1066 
1067 // --- DdeService::IsBusy() ----------------------------------------
1068 
IsBusy()1069 sal_Bool __EXPORT DdeService::IsBusy()
1070 {
1071 	return sal_False;
1072 }
1073 
1074 // --- DdeService::GetHelp() ----------------------------------------
1075 
GetHelp()1076 String __EXPORT DdeService::GetHelp()
1077 {
1078 	return String();
1079 }
1080 
MakeItem(const String &)1081 sal_Bool DdeTopic::MakeItem( const String& )
1082 {
1083 	return sal_False;
1084 }
1085 
MakeTopic(const String &)1086 sal_Bool DdeService::MakeTopic( const String& )
1087 {
1088 	return sal_False;
1089 }
1090 
SysTopicGet(const String &)1091 String DdeService::SysTopicGet( const String& )
1092 {
1093 	return String();
1094 }
1095 
SysTopicExecute(const String *)1096 sal_Bool DdeService::SysTopicExecute( const String* )
1097 {
1098 	return sal_False;
1099 }
1100 
1101