bump product version to 5.0.4.1
[LibreOffice.git] / svl / source / svdde / ddesvr.cxx
blob923222b7b9a19e18cd0fa319da21f43edb9abbd9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #define UNICODE
22 #include "ddeimp.hxx"
23 #include <algorithm>
24 #include <comphelper/string.hxx>
25 #include <rtl/ustring.hxx>
26 #include <svl/svdde.hxx>
27 #include <tools/debug.hxx>
28 #include <osl/thread.h>
29 #include <o3tl/sorted_vector.hxx>
31 enum DdeItemType
33 DDEITEM,
34 DDEGETPUTITEM
37 struct DdeItemImpData
39 sal_uLong nHCnv;
40 sal_uInt16 nCnt;
42 DdeItemImpData( sal_uLong nH ) : nHCnv( nH ), nCnt( 1 ) {}
45 class DdeItemImp {
46 public:
47 DdeItemImp() : mvData() {}
49 size_t size() const { return mvData.size(); }
51 std::vector<DdeItemImpData>::iterator begin() { return mvData.begin(); }
53 void erase(std::vector<DdeItemImpData>::iterator it) { mvData.erase(it); }
55 void push_back(const DdeItemImpData& rData) { mvData.push_back(rData); }
57 DdeItemImpData& operator[](size_t i) { return mvData[i]; }
59 private:
60 std::vector<DdeItemImpData> mvData;
63 HDDEDATA CALLBACK DdeInternal::SvrCallback(
64 WORD nCode, WORD nCbType, HCONV hConv, HSZ hText1, HSZ hText2,
65 HDDEDATA hData, DWORD, DWORD )
67 DdeServices& rAll = DdeService::GetServices();
68 DdeService* pService;
69 DdeTopic* pTopic;
70 DdeItem* pItem;
71 DdeData* pData;
72 Conversation* pC;
74 DdeInstData* pInst = ImpGetInstData();
75 DBG_ASSERT(pInst,"SVDDE:No instance data");
77 switch( nCode )
79 case XTYP_WILDCONNECT:
81 int nTopics = 0;
83 TCHAR chTopicBuf[250];
84 if( hText1 )
85 DdeQueryString( pInst->hDdeInstSvr, hText1, chTopicBuf,
86 sizeof(chTopicBuf)/sizeof(TCHAR), CP_WINUNICODE );
88 for (DdeServices::iterator aI = rAll.begin(); aI != rAll.end(); ++aI)
90 pService = *aI;
91 if ( !hText2 || ( *pService->pName == hText2 ) )
93 OUString sTopics( pService->Topics() );
94 if (!sTopics.isEmpty())
96 if( hText1 )
98 sal_Int32 n = 0;
99 while( -1 != n )
101 OUString s( sTopics.getToken( 0, '\t', n ));
102 if( s == reinterpret_cast<const sal_Unicode*>(chTopicBuf) )
103 ++nTopics;
106 else
107 nTopics += comphelper::string::getTokenCount(sTopics, '\t');
112 if( !nTopics )
113 return (HDDEDATA)NULL;
115 HSZPAIR* pPairs = new HSZPAIR [nTopics + 1];
117 HSZPAIR* q = pPairs;
118 for (DdeServices::iterator aI = rAll.begin(); aI != rAll.end(); ++aI)
120 pService = *aI;
121 if ( !hText2 || (*pService->pName == hText2 ) )
123 OUString sTopics( pService->Topics() );
124 sal_Int32 n = 0;
125 while( -1 != n )
127 OUString s( sTopics.getToken( 0, '\t', n ));
128 s = comphelper::string::remove(s, '\n');
129 s = comphelper::string::remove(s, '\r');
130 if( !hText1 || s == reinterpret_cast<const sal_Unicode*>(chTopicBuf) )
132 DdeString aDStr( pInst->hDdeInstSvr, s );
133 pTopic = FindTopic( *pService, (HSZ)aDStr );
134 if( pTopic )
136 q->hszSvc = *pService->pName;
137 q->hszTopic = *pTopic->pName;
138 q++;
145 q->hszSvc = NULL;
146 q->hszTopic = NULL;
147 HDDEDATA h = DdeCreateDataHandle(
148 pInst->hDdeInstSvr, (LPBYTE) pPairs,
149 sizeof(HSZPAIR) * (nTopics+1),
150 0, NULL, nCbType, 0);
151 delete [] pPairs;
152 return h;
155 case XTYP_CONNECT:
156 pService = FindService( hText2 );
157 if ( pService)
158 pTopic = FindTopic( *pService, hText1 );
159 else
160 pTopic = NULL;
161 if ( pTopic )
162 return (HDDEDATA)DDE_FACK;
163 else
164 return (HDDEDATA) NULL;
166 case XTYP_CONNECT_CONFIRM:
167 pService = FindService( hText2 );
168 if ( pService )
170 pTopic = FindTopic( *pService, hText1 );
171 if ( pTopic )
173 pTopic->Connect( (sal_IntPtr) hConv );
174 pC = new Conversation;
175 pC->hConv = hConv;
176 pC->pTopic = pTopic;
177 pService->pConv->push_back( pC );
180 return (HDDEDATA)NULL;
183 for (DdeServices::iterator aI = rAll.begin(); aI != rAll.end(); ++aI)
185 pService = *aI;
186 for ( size_t i = 0, n = pService->pConv->size(); i < n; ++i )
188 pC = (*pService->pConv)[ i ];
189 if ( pC->hConv == hConv )
190 goto found;
194 return (HDDEDATA) DDE_FNOTPROCESSED;
196 found:
197 if ( nCode == XTYP_DISCONNECT)
199 pC->pTopic->_Disconnect( (sal_IntPtr) hConv );
200 for ( ConvList::iterator it = pService->pConv->begin();
201 it != pService->pConv->end();
202 ++it
204 if ( *it == pC )
206 delete *it;
207 pService->pConv->erase( it );
208 break;
211 return (HDDEDATA)NULL;
214 bool bExec = nCode == XTYP_EXECUTE;
215 pTopic = pC->pTopic;
216 if ( pTopic && !bExec )
217 pItem = FindItem( *pTopic, hText2 );
218 else
219 pItem = NULL;
221 if ( !bExec && !pService->HasCbFormat( nCbType ) )
222 pItem = NULL;
223 if ( !pItem && !bExec )
224 return (HDDEDATA)DDE_FNOTPROCESSED;
225 if ( pItem )
226 pTopic->aItem = pItem->GetName();
227 else
228 (pTopic->aItem).clear();
230 bool bRes = false;
231 pInst->hCurConvSvr = (sal_IntPtr)hConv;
232 switch( nCode )
234 case XTYP_REQUEST:
235 case XTYP_ADVREQ:
237 OUString aRes; // Must be free not until the end!
238 if ( pTopic->IsSystemTopic() )
240 if ( pTopic->aItem == reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_TOPICS) )
241 aRes = pService->Topics();
242 else if ( pTopic->aItem == reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_SYSITEMS) )
243 aRes = pService->SysItems();
244 else if ( pTopic->aItem == reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_STATUS) )
245 aRes = pService->Status();
246 else if ( pTopic->aItem == reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_FORMATS) )
247 aRes = pService->Formats();
248 else if ( pTopic->aItem == reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_HELP) )
249 aRes = pService->GetHelp();
250 else
251 aRes = pService->SysTopicGet( pTopic->aItem );
253 if ( !aRes.isEmpty() )
254 pData = new DdeData( aRes );
255 else
256 pData = NULL;
258 else if( DDEGETPUTITEM == pItem->nType )
260 pData = ((DdeGetPutItem*)pItem)->Get( DdeData::GetInternalFormat( nCbType ) );
262 else
264 pData = pTopic->Get( DdeData::GetInternalFormat( nCbType ));
267 if ( pData )
269 return DdeCreateDataHandle( pInst->hDdeInstSvr,
270 (LPBYTE)pData->pImp->pData,
271 pData->pImp->nData,
272 0, hText2,
273 DdeData::GetExternalFormat(
274 pData->pImp->nFmt ),
275 0 );
278 break;
280 case XTYP_POKE:
281 if ( !pTopic->IsSystemTopic() )
283 DdeData d;
284 d.pImp->hData = hData;
285 d.pImp->nFmt = DdeData::GetInternalFormat( nCbType );
286 d.Lock();
287 if( DDEGETPUTITEM == pItem->nType )
288 bRes = ((DdeGetPutItem*)pItem)->Put( &d );
289 else
290 bRes = pTopic->Put( &d );
292 pInst->hCurConvSvr = 0;
293 if ( bRes )
294 return (HDDEDATA)DDE_FACK;
295 else
296 return (HDDEDATA) DDE_FNOTPROCESSED;
298 case XTYP_ADVSTART:
300 // Is the Item turning into a HotLink for the first time?
301 if( !pItem->pImpData && pTopic->StartAdviseLoop() )
303 // Then the Item has been exchanged
304 std::vector<DdeItem*>::iterator it(std::find(pTopic->aItems.begin(),
305 pTopic->aItems.end(),
306 pItem));
307 if (it != pTopic->aItems.end())
308 pTopic->aItems.erase(it);
310 std::vector<DdeItem*>::iterator iter;
311 for( iter = pTopic->aItems.begin();
312 iter != pTopic->aItems.end();
313 ++iter )
315 if( *(*iter)->pName == hText2 )
317 // It was exchanged indeed
318 delete pItem;
319 pItem = 0;
320 break;
324 if( pItem )
325 // It was not exchange, so back in
326 pTopic->aItems.push_back(pItem);
327 else
328 pItem = iter != pTopic->aItems.end() ? *iter : NULL;
331 if (pItem)
333 pItem->IncMonitor( (sal_IntPtr)hConv );
334 pInst->hCurConvSvr = 0;
337 return (HDDEDATA)sal_True;
339 case XTYP_ADVSTOP:
340 pItem->DecMonitor( (sal_IntPtr)hConv );
341 if( !pItem->pImpData )
342 pTopic->StopAdviseLoop();
343 pInst->hCurConvSvr = 0;
344 return (HDDEDATA)sal_True;
346 case XTYP_EXECUTE:
348 DdeData aExec;
349 aExec.pImp->hData = hData;
350 aExec.pImp->nFmt = DdeData::GetInternalFormat( nCbType );
351 aExec.Lock();
352 OUString aName;
354 aName = (const sal_Unicode *)aExec.pImp->pData;
356 if( pTopic->IsSystemTopic() )
357 bRes = pService->SysTopicExecute( &aName );
358 else
359 bRes = pTopic->Execute( &aName );
361 pInst->hCurConvSvr = 0;
362 if ( bRes )
363 return (HDDEDATA)DDE_FACK;
364 else
365 return (HDDEDATA)DDE_FNOTPROCESSED;
368 return (HDDEDATA)NULL;
371 DdeService* DdeInternal::FindService( HSZ hService )
373 DdeServices& rSvc = DdeService::GetServices();
374 for (DdeServices::iterator aI = rSvc.begin(); aI != rSvc.end(); ++aI)
376 DdeService* s = *aI;
377 if ( *s->pName == hService )
378 return s;
381 return NULL;
384 DdeTopic* DdeInternal::FindTopic( DdeService& rService, HSZ hTopic )
386 std::vector<DdeTopic*>::iterator iter;
387 std::vector<DdeTopic*> &rTopics = rService.aTopics;
388 bool bContinue = false;
389 DdeInstData* pInst = ImpGetInstData();
390 DBG_ASSERT(pInst,"SVDDE:No instance data");
393 { // middle check loop
394 for ( iter = rTopics.begin(); iter != rTopics.end(); ++iter )
396 if ( *(*iter)->pName == hTopic )
397 return *iter;
400 bContinue = !bContinue;
401 if( !bContinue )
402 break;
404 // Let's query our subclass
405 TCHAR chBuf[250];
406 DdeQueryString(pInst->hDdeInstSvr,hTopic,chBuf,sizeof(chBuf)/sizeof(TCHAR),CP_WINUNICODE );
407 bContinue = rService.MakeTopic( reinterpret_cast<const sal_Unicode*>(chBuf) );
408 // We need to search again
410 while( bContinue );
412 return 0;
415 DdeItem* DdeInternal::FindItem( DdeTopic& rTopic, HSZ hItem )
417 std::vector<DdeItem*>::iterator iter;
418 std::vector<DdeItem*> &rItems = rTopic.aItems;
419 DdeInstData* pInst = ImpGetInstData();
420 DBG_ASSERT(pInst,"SVDDE:No instance data");
421 bool bContinue = false;
424 { // middle check loop
425 for ( iter = rItems.begin(); iter != rItems.end(); ++iter )
427 if ( *(*iter)->pName == hItem )
428 return *iter;
430 bContinue = !bContinue;
431 if( !bContinue )
432 break;
434 // Let's query our subclass
435 TCHAR chBuf[250];
436 DdeQueryString(pInst->hDdeInstSvr,hItem,chBuf,sizeof(chBuf)/sizeof(TCHAR),CP_WINUNICODE );
437 bContinue = rTopic.MakeItem( reinterpret_cast<const sal_Unicode*>(chBuf) );
438 // We need to search again
440 while( bContinue );
442 return 0;
445 DdeService::DdeService( const OUString& rService )
447 DdeInstData* pInst = ImpGetInstData();
448 if( !pInst )
449 pInst = ImpInitInstData();
450 pInst->nRefCount++;
451 pInst->nInstanceSvr++;
453 if ( !pInst->hDdeInstSvr )
455 nStatus = sal::static_int_cast< short >(
456 DdeInitialize( &pInst->hDdeInstSvr,
457 (PFNCALLBACK)DdeInternal::SvrCallback,
458 APPCLASS_STANDARD |
459 CBF_SKIP_REGISTRATIONS |
460 CBF_SKIP_UNREGISTRATIONS, 0L ) );
461 pInst->pServicesSvr = new DdeServices;
463 else
464 nStatus = DMLERR_NO_ERROR;
466 pConv = new ConvList;
468 if ( pInst->pServicesSvr )
469 pInst->pServicesSvr->push_back( this );
471 pName = new DdeString( pInst->hDdeInstSvr, rService );
472 if ( nStatus == DMLERR_NO_ERROR )
474 if ( !DdeNameService( pInst->hDdeInstSvr, *pName, NULL,
475 DNS_REGISTER | DNS_FILTEROFF ) )
477 nStatus = DMLERR_SYS_ERROR;
480 AddFormat( SotClipboardFormatId::STRING );
481 pSysTopic = new DdeTopic( reinterpret_cast<const sal_Unicode*>(SZDDESYS_TOPIC) );
482 pSysTopic->AddItem( DdeItem( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_TOPICS) ) );
483 pSysTopic->AddItem( DdeItem( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_SYSITEMS) ) );
484 pSysTopic->AddItem( DdeItem( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_STATUS) ) );
485 pSysTopic->AddItem( DdeItem( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_FORMATS) ) );
486 pSysTopic->AddItem( DdeItem( reinterpret_cast<const sal_Unicode*>(SZDDESYS_ITEM_HELP) ) );
487 AddTopic( *pSysTopic );
490 DdeService::~DdeService()
492 DdeInstData* pInst = ImpGetInstData();
493 DBG_ASSERT(pInst,"SVDDE:No instance data");
494 if ( pInst->pServicesSvr )
495 pInst->pServicesSvr->erase(std::remove(pInst->pServicesSvr->begin(), pInst->pServicesSvr->end(), this), pInst->pServicesSvr->end());
497 delete pSysTopic;
498 delete pName;
500 pInst->nInstanceSvr--;
501 pInst->nRefCount--;
502 if ( !pInst->nInstanceSvr && pInst->hDdeInstSvr )
504 if( DdeUninitialize( pInst->hDdeInstSvr ) )
506 pInst->hDdeInstSvr = 0;
507 delete pInst->pServicesSvr;
508 pInst->pServicesSvr = NULL;
509 if( pInst->nRefCount == 0)
510 ImpDeinitInstData();
513 delete pConv;
516 const OUString DdeService::GetName() const
518 return pName->toOUString();
521 DdeServices& DdeService::GetServices()
523 DdeInstData* pInst = ImpGetInstData();
524 DBG_ASSERT(pInst,"SVDDE:No instance data");
525 return *(pInst->pServicesSvr);
528 void DdeService::AddTopic( const DdeTopic& rTopic )
530 RemoveTopic( rTopic );
531 aTopics.push_back((DdeTopic *) &rTopic);
534 void DdeService::RemoveTopic( const DdeTopic& rTopic )
536 std::vector<DdeTopic*>::iterator iter;
537 for ( iter = aTopics.begin(); iter != aTopics.end(); ++iter )
539 if ( !DdeCmpStringHandles (*(*iter)->pName, *rTopic.pName ) )
541 aTopics.erase(iter);
542 // Delete all conversions!
543 // Or else we work on deleted topics!
544 for( size_t n = pConv->size(); n; )
546 Conversation* pC = (*pConv)[ --n ];
547 if( pC->pTopic == &rTopic )
549 ConvList::iterator it = pConv->begin();
550 ::std::advance( it, n );
551 delete *it;
552 pConv->erase( it );
555 break;
560 bool DdeService::HasCbFormat( sal_uInt16 nFmt )
562 for ( size_t i = 0, n = aFormats.size(); i < n; ++i )
563 if ( aFormats[ i ] == nFmt )
564 return true;
565 return false;
568 bool DdeService::HasFormat(SotClipboardFormatId nFmt)
570 return HasCbFormat( (sal_uInt16)DdeData::GetExternalFormat( nFmt ));
573 void DdeService::AddFormat(SotClipboardFormatId nFmt)
575 sal_uLong nExternalFmt = DdeData::GetExternalFormat( nFmt );
576 for ( size_t i = 0, n = aFormats.size(); i < n; ++i )
577 if ( (sal_uLong) aFormats[ i ] == nExternalFmt )
578 return;
579 aFormats.push_back( nExternalFmt );
582 void DdeService::RemoveFormat(SotClipboardFormatId nFmt)
584 sal_uLong nExternalFmt = DdeData::GetExternalFormat( nFmt );
585 for ( DdeFormats::iterator it = aFormats.begin(); it != aFormats.end(); ++it )
587 if ( (sal_uLong) *it == nExternalFmt )
589 aFormats.erase( it );
590 break;
595 DdeTopic::DdeTopic( const OUString& rName )
597 DdeInstData* pInst = ImpGetInstData();
598 DBG_ASSERT(pInst,"SVDDE:No instance data");
599 pName = new DdeString( pInst->hDdeInstSvr, rName );
602 DdeTopic::~DdeTopic()
604 std::vector<DdeItem*>::iterator iter;
605 for (iter = aItems.begin(); iter != aItems.end(); ++iter)
607 (*iter)->pMyTopic = 0;
608 delete *iter;
611 delete pName;
614 const OUString DdeTopic::GetName() const
616 return pName->toOUString();
619 bool DdeTopic::IsSystemTopic()
621 return GetName() == reinterpret_cast<const sal_Unicode*>(SZDDESYS_TOPIC);
624 DdeItem* DdeTopic::AddItem( const DdeItem& r )
626 DdeItem* s;
627 if( DDEGETPUTITEM == r.nType )
628 s = new DdeGetPutItem( r );
629 else
630 s = new DdeItem( r );
632 if ( s )
634 aItems.push_back( s );
635 s->pMyTopic = this;
637 return s;
640 void DdeTopic::InsertItem( DdeItem* pNew )
642 if( pNew )
644 aItems.push_back( pNew );
645 pNew->pMyTopic = this;
649 void DdeTopic::RemoveItem( const DdeItem& r )
651 std::vector<DdeItem*>::iterator iter;
652 for (iter = aItems.begin(); iter != aItems.end(); ++iter)
654 if ( !DdeCmpStringHandles (*(*iter)->pName, *r.pName ) )
655 break;
658 if ( iter != aItems.end() )
660 (*iter)->pMyTopic = 0;
661 delete *iter;
662 aItems.erase(iter);
666 void DdeTopic::NotifyClient( const OUString& rItem )
668 std::vector<DdeItem*>::iterator iter;
669 DdeInstData* pInst = ImpGetInstData();
670 DBG_ASSERT(pInst,"SVDDE:No instance data");
671 for ( iter = aItems.begin(); iter != aItems.end(); ++iter)
673 if ( (*iter)->GetName().equals(rItem) && (*iter)->pImpData)
675 DdePostAdvise( pInst->hDdeInstSvr, *pName, *(*iter)->pName );
676 break;
681 void DdeTopic::Connect( sal_IntPtr nId )
683 aConnectLink.Call( (void*)nId );
686 void DdeTopic::Disconnect( sal_IntPtr nId )
688 aDisconnectLink.Call( (void*)nId );
691 void DdeTopic::_Disconnect( sal_IntPtr nId )
693 std::vector<DdeItem*>::iterator iter;
694 for (iter = aItems.begin(); iter != aItems.end(); ++iter)
695 (*iter)->DecMonitor( nId );
697 Disconnect( nId );
700 DdeData* DdeTopic::Get(SotClipboardFormatId nFmt)
702 if ( aGetLink.IsSet() )
703 return (DdeData*)aGetLink.Call( (void*)nFmt );
704 else
705 return NULL;
708 bool DdeTopic::Put( const DdeData* r )
710 if ( aPutLink.IsSet() )
711 return aPutLink.Call( (void*) r );
712 else
713 return false;
716 bool DdeTopic::Execute( const OUString* r )
718 if ( aExecLink.IsSet() )
719 return aExecLink.Call( (void*)r );
720 else
721 return false;
724 long DdeTopic::GetConvId()
726 DdeInstData* pInst = ImpGetInstData();
727 DBG_ASSERT(pInst,"SVDDE:No instance data");
728 return pInst->hCurConvSvr;
731 bool DdeTopic::StartAdviseLoop()
733 return false;
736 bool DdeTopic::StopAdviseLoop()
738 return false;
741 DdeItem::DdeItem( const sal_Unicode* p )
743 DdeInstData* pInst = ImpGetInstData();
744 DBG_ASSERT(pInst,"SVDDE:No instance data");
745 pName = new DdeString( pInst->hDdeInstSvr, p );
746 nType = DDEITEM;
747 pMyTopic = 0;
748 pImpData = 0;
751 DdeItem::DdeItem( const OUString& r)
753 DdeInstData* pInst = ImpGetInstData();
754 DBG_ASSERT(pInst,"SVDDE:No instance data");
755 pName = new DdeString( pInst->hDdeInstSvr, r );
756 nType = DDEITEM;
757 pMyTopic = 0;
758 pImpData = 0;
761 DdeItem::DdeItem( const DdeItem& r)
763 DdeInstData* pInst = ImpGetInstData();
764 DBG_ASSERT(pInst,"SVDDE:No instance data");
765 pName = new DdeString( pInst->hDdeInstSvr, r.pName->toOUString() );
766 nType = DDEITEM;
767 pMyTopic = 0;
768 pImpData = 0;
771 DdeItem::~DdeItem()
773 if( pMyTopic )
774 pMyTopic->aItems.erase(std::remove(pMyTopic->aItems.begin(),
775 pMyTopic->aItems.end(),this));
776 delete pName;
777 delete pImpData;
780 const OUString DdeItem::GetName() const
782 return pName->toOUString();
785 void DdeItem::NotifyClient()
787 if( pMyTopic && pImpData )
789 DdeInstData* pInst = ImpGetInstData();
790 DBG_ASSERT(pInst,"SVDDE:No instance data");
791 DdePostAdvise( pInst->hDdeInstSvr, *pMyTopic->pName, *pName );
795 void DdeItem::IncMonitor( sal_uLong nHCnv )
797 if( !pImpData )
799 pImpData = new DdeItemImp;
800 if( DDEGETPUTITEM == nType )
801 ((DdeGetPutItem*)this)->AdviseLoop( true );
803 else
805 for( sal_uInt16 n = pImpData->size(); n; )
806 if( (*pImpData)[ --n ].nHCnv == nHCnv )
808 ++(*pImpData)[ n ].nHCnv;
809 return ;
813 pImpData->push_back( DdeItemImpData( nHCnv ) );
816 void DdeItem::DecMonitor( sal_uLong nHCnv )
818 if( pImpData )
820 for( sal_uInt16 n = 0; n < pImpData->size(); ++n )
822 DdeItemImpData* pData = &(*pImpData)[n];
823 if( pData->nHCnv == nHCnv )
825 if( !pData->nCnt || !--pData->nCnt )
827 if( 1 < pImpData->size() )
829 pImpData->erase(pImpData->begin() + n);
831 else
833 delete pImpData, pImpData = 0;
834 if( DDEGETPUTITEM == nType )
835 ((DdeGetPutItem*)this)->AdviseLoop( false );
838 return ;
844 short DdeItem::GetLinks()
846 short nCnt = 0;
847 if( pImpData )
849 for( sal_uInt16 n = pImpData->size(); n; )
851 nCnt = nCnt + (*pImpData)[ --n ].nCnt;
854 return nCnt;
857 DdeGetPutItem::DdeGetPutItem( const sal_Unicode* p )
858 : DdeItem( p )
860 nType = DDEGETPUTITEM;
863 DdeGetPutItem::DdeGetPutItem( const OUString& rStr )
864 : DdeItem( rStr )
866 nType = DDEGETPUTITEM;
869 DdeGetPutItem::DdeGetPutItem( const DdeItem& rItem )
870 : DdeItem( rItem )
872 nType = DDEGETPUTITEM;
875 DdeData* DdeGetPutItem::Get(SotClipboardFormatId)
877 return 0;
880 bool DdeGetPutItem::Put( const DdeData* )
882 return false;
885 void DdeGetPutItem::AdviseLoop( bool )
889 OUString DdeService::SysItems()
891 OUString s;
892 std::vector<DdeTopic*>::iterator iter;
893 std::vector<DdeItem*>::iterator iterItem;
894 for ( iter = aTopics.begin(); iter != aTopics.end(); ++iter )
896 if ( (*iter)->GetName() == reinterpret_cast<const sal_Unicode*>(SZDDESYS_TOPIC) )
898 short n = 0;
899 for ( iterItem = (*iter)->aItems.begin(); iterItem != (*iter)->aItems.end(); ++iterItem, n++ )
901 if ( n )
902 s += "\t";
903 s += (*iterItem)->GetName();
905 s += "\r\n";
909 return s;
912 OUString DdeService::Topics()
914 OUString s;
915 std::vector<DdeTopic*>::iterator iter;
916 short n = 0;
918 for ( iter = aTopics.begin(); iter != aTopics.end(); ++iter, n++ )
920 if ( n )
921 s += "\t";
922 s += (*iter)->GetName();
924 s += "\r\n";
926 return s;
929 OUString DdeService::Formats()
931 OUString s;
932 short n = 0;
934 for (size_t i = 0; i < aFormats.size(); ++i, ++n)
936 long f = aFormats[ i ];
937 if ( n )
938 s += "\t";
940 switch( (sal_uInt16)f )
942 case CF_TEXT:
943 s += "TEXT";
944 break;
945 case CF_BITMAP:
946 s += "BITMAP";
947 break;
948 default:
950 TCHAR buf[128];
951 GetClipboardFormatName( (UINT)f, buf, sizeof(buf) / sizeof(TCHAR) );
952 s += OUString(reinterpret_cast<sal_Unicode*>(buf));
954 break;
958 s += "\r\n";
960 return s;
963 OUString DdeService::Status()
965 return IsBusy() ? OUString("Busy\r\n") : OUString("Ready\r\n");
968 bool DdeService::IsBusy()
970 return false;
973 OUString DdeService::GetHelp()
975 return OUString();
978 bool DdeTopic::MakeItem( const OUString& )
980 return false;
983 bool DdeService::MakeTopic( const OUString& )
985 return false;
988 OUString DdeService::SysTopicGet( const OUString& )
990 return OUString();
993 bool DdeService::SysTopicExecute( const OUString* )
995 return false;
998 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */