xref: /AOO41X/main/svl/source/svdde/ddesvr.cxx (revision 40df464ee80f942fd2baf5effc726656f4be12a0)
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