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 = (long)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 long DdeTopic::GetConvId()
771 {
772 DdeInstData* pInst = ImpGetInstData();
773 DBG_ASSERT(pInst,"SVDDE:No instance data");
774 return 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