1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
25 #include <svl/svdde.hxx>
27 #include <osl/thread.h>
28 #include <tools/debug.hxx>
29 #include <tools/solarmutex.hxx>
30 #include <osl/mutex.hxx>
32 DdeInstData
* ImpInitInstData()
34 DdeInstData
* pData
= new DdeInstData
;
36 DdeInstData
** ppInst
= (DdeInstData
**)GetAppData( SHL_SVDDE
);
41 void ImpDeinitInstData()
43 DdeInstData
** ppInst
= (DdeInstData
**)GetAppData( SHL_SVDDE
);
55 HDDEDATA CALLBACK
DdeInternal::CliCallback( WORD nCode
, WORD nCbType
,
56 HCONV hConv
, HSZ
, HSZ hText2
,
57 HDDEDATA hData
, DWORD nInfo1
, DWORD
)
59 HDDEDATA nRet
= DDE_FNOTPROCESSED
;
60 const std::vector
<DdeConnection
*> &rAll
= DdeConnection::GetConnections();
61 DdeConnection
* self
= 0;
63 DdeInstData
* pInst
= ImpGetInstData();
64 DBG_ASSERT(pInst
,"SVDDE:No instance data");
66 for ( size_t i
= 0; i
< rAll
.size(); ++i
)
70 if ( self
->pImp
->hConv
== hConv
)
77 std::vector
<DdeTransaction
*>::iterator iter
;
78 for( iter
= self
->aTransactions
.begin(); iter
!= self
->aTransactions
.end(); ++iter
)
82 case XTYP_XACT_COMPLETE
:
83 if( (DWORD
)(*iter
)->nId
== nInfo1
)
85 nCode
= (*iter
)->nType
& (XCLASS_MASK
| XTYP_MASK
);
86 (*iter
)->bBusy
= false;
87 (*iter
)->Done( 0 != hData
);
93 self
->pImp
->hConv
= DdeReconnect( hConv
);
94 self
->pImp
->nStatus
= self
->pImp
->hConv
96 : DdeGetLastError( pInst
->hDdeInstCli
);
97 iter
= self
->aTransactions
.end();
103 bFound
= *(*iter
)->pName
== hText2
;
110 if( iter
!= self
->aTransactions
.end() )
117 static_cast<DdeLink
*>(*iter
)->Notify();
118 nRet
= (HDDEDATA
)DDE_FACK
;
124 if( !hData
&& XTYP_REQUEST
== nCode
)
130 d
.pImp
->hData
= hData
;
131 d
.pImp
->nFmt
= DdeData::GetInternalFormat( nCbType
);
134 nRet
= (HDDEDATA
)DDE_FACK
;
142 DdeConnection::DdeConnection( const OUString
& rService
, const OUString
& rTopic
)
145 pImp
->nStatus
= DMLERR_NO_ERROR
;
148 DdeInstData
* pInst
= ImpGetInstData();
150 pInst
= ImpInitInstData();
152 pInst
->nInstanceCli
++;
153 if ( !pInst
->hDdeInstCli
)
155 pImp
->nStatus
= DdeInitialize( &pInst
->hDdeInstCli
,
156 (PFNCALLBACK
)DdeInternal::CliCallback
,
157 APPCLASS_STANDARD
| APPCMD_CLIENTONLY
|
158 CBF_FAIL_ALLSVRXACTIONS
|
159 CBF_SKIP_REGISTRATIONS
|
160 CBF_SKIP_UNREGISTRATIONS
, 0L );
163 pService
= new DdeString( pInst
->hDdeInstCli
, rService
);
164 pTopic
= new DdeString( pInst
->hDdeInstCli
, rTopic
);
166 if ( pImp
->nStatus
== DMLERR_NO_ERROR
)
168 pImp
->hConv
= DdeConnect( pInst
->hDdeInstCli
,*pService
,*pTopic
, NULL
);
170 pImp
->nStatus
= DdeGetLastError( pInst
->hDdeInstCli
);
173 pInst
->aConnections
.push_back( this );
176 DdeConnection::~DdeConnection()
179 DdeDisconnect( pImp
->hConv
);
184 DdeInstData
* pInst
= ImpGetInstData();
185 DBG_ASSERT(pInst
,"SVDDE:No instance data");
187 std::vector
<DdeConnection
*>::iterator
it(std::find(pInst
->aConnections
.begin(),
188 pInst
->aConnections
.end(),
190 if (it
!= pInst
->aConnections
.end())
191 pInst
->aConnections
.erase(it
);
193 pInst
->nInstanceCli
--;
195 if ( !pInst
->nInstanceCli
&& pInst
->hDdeInstCli
)
197 if( DdeUninitialize( pInst
->hDdeInstCli
) )
199 pInst
->hDdeInstCli
= 0;
200 if( pInst
->nRefCount
== 0 )
207 bool DdeConnection::IsConnected()
211 if ( DdeQueryConvInfo( pImp
->hConv
, QID_SYNC
, &c
) )
215 DdeInstData
* pInst
= ImpGetInstData();
216 pImp
->hConv
= DdeReconnect( pImp
->hConv
);
217 pImp
->nStatus
= pImp
->hConv
? DMLERR_NO_ERROR
: DdeGetLastError( pInst
->hDdeInstCli
);
218 return pImp
->nStatus
== DMLERR_NO_ERROR
;
222 const OUString
DdeConnection::GetServiceName()
224 return pService
->toOUString();
227 const OUString
DdeConnection::GetTopicName()
229 return pTopic
->toOUString();
232 sal_IntPtr
DdeConnection::GetConvId()
234 return (sal_IntPtr
)pImp
->hConv
;
237 const std::vector
<DdeConnection
*>& DdeConnection::GetConnections()
239 DdeInstData
* pInst
= ImpGetInstData();
240 DBG_ASSERT(pInst
,"SVDDE:No instance data");
241 return pInst
->aConnections
;
244 DdeTransaction::DdeTransaction( DdeConnection
& d
, const OUString
& rItemName
,
248 DdeInstData
* pInst
= ImpGetInstData();
249 pName
= new DdeString( pInst
->hDdeInstCli
, rItemName
);
255 rDde
.aTransactions
.push_back( this );
258 DdeTransaction::~DdeTransaction()
260 if ( nId
&& rDde
.pImp
->hConv
)
262 DdeInstData
* pInst
= ImpGetInstData();
263 DdeAbandonTransaction( pInst
->hDdeInstCli
, rDde
.pImp
->hConv
, nId
);
267 rDde
.aTransactions
.erase(std::remove(rDde
.aTransactions
.begin(),
268 rDde
.aTransactions
.end(),this));
271 void DdeTransaction::Execute()
274 void* pData
= (void*)(const void *)aDdeData
;
275 DWORD nData
= (DWORD
)(long)aDdeData
;
276 SotClipboardFormatId nIntFmt
= aDdeData
.pImp
->nFmt
;
277 UINT nExtFmt
= DdeData::GetExternalFormat( nIntFmt
);
278 DdeInstData
* pInst
= ImpGetInstData();
280 if ( nType
== XTYP_EXECUTE
)
282 if ( nType
!= XTYP_EXECUTE
&& nType
!= XTYP_POKE
)
289 HDDEDATA hData
= DdeClientTransaction( (unsigned char*)pData
,
290 nData
, rDde
.pImp
->hConv
,
291 hItem
, nExtFmt
, (UINT
)nType
,
292 (DWORD
)nTime
, (DWORD FAR
*)NULL
);
294 rDde
.pImp
->nStatus
= DdeGetLastError( pInst
->hDdeInstCli
);
295 if( hData
&& nType
== XTYP_REQUEST
)
299 d
.pImp
->hData
= hData
;
300 d
.pImp
->nFmt
= nIntFmt
;
304 DdeFreeDataHandle( hData
);
309 if ( nId
&& rDde
.pImp
->hConv
)
310 DdeAbandonTransaction( pInst
->hDdeInstCli
, rDde
.pImp
->hConv
, nId
);
313 HDDEDATA hRet
= DdeClientTransaction( (unsigned char*)pData
, nData
,
314 rDde
.pImp
->hConv
, hItem
, nExtFmt
,
315 (UINT
)nType
, TIMEOUT_ASYNC
,
316 (DWORD FAR
*) ((long*) &nId
) );
317 rDde
.pImp
->nStatus
= hRet
? DMLERR_NO_ERROR
318 : DdeGetLastError( pInst
->hDdeInstCli
);
322 const OUString
DdeTransaction::GetName() const
324 return pName
->toOUString();
327 void DdeTransaction::Data( const DdeData
* p
)
329 if ( ::tools::SolarMutex::Acquire() )
331 aData
.Call( (void*)p
);
332 ::tools::SolarMutex::Release();
336 void DdeTransaction::Done( bool bDataValid
)
338 const sal_uIntPtr
nDataValid(bDataValid
);
339 aDone
.Call( reinterpret_cast<void*>(nDataValid
) );
342 DdeLink::DdeLink( DdeConnection
& d
, const OUString
& aItemName
, long n
)
343 : DdeTransaction (d
, aItemName
, n
)
349 nType
= (sal_uInt16
)XTYP_ADVSTOP
;
353 void DdeLink::Notify()
355 aNotify
.Call( NULL
);
358 DdeRequest::DdeRequest( DdeConnection
& d
, const OUString
& i
, long n
)
359 : DdeTransaction( d
, i
, n
)
361 nType
= XTYP_REQUEST
;
364 DdeWarmLink::DdeWarmLink( DdeConnection
& d
, const OUString
& i
, long n
)
367 nType
= XTYP_ADVSTART
| XTYPF_NODATA
;
370 DdeHotLink::DdeHotLink( DdeConnection
& d
, const OUString
& i
, long n
)
373 nType
= XTYP_ADVSTART
;
376 DdePoke::DdePoke( DdeConnection
& d
, const OUString
& i
, const char* p
,
377 long l
, SotClipboardFormatId f
, long n
)
378 : DdeTransaction( d
, i
, n
)
380 aDdeData
= DdeData( p
, l
, f
);
384 DdePoke::DdePoke( DdeConnection
& d
, const OUString
& i
, const OUString
& rData
,
386 : DdeTransaction( d
, i
, n
)
388 aDdeData
= DdeData( (void*) rData
.getStr(), sizeof(sal_Unicode
) * (rData
.getLength()), SotClipboardFormatId::STRING
);
392 DdePoke::DdePoke( DdeConnection
& d
, const OUString
& i
, const DdeData
& rData
,
394 : DdeTransaction( d
, i
, n
)
400 DdeExecute::DdeExecute( DdeConnection
& d
, const OUString
& rData
, long n
)
401 : DdeTransaction( d
, OUString(), n
)
403 aDdeData
= DdeData( (void*)rData
.getStr(), sizeof(sal_Unicode
) * (rData
.getLength() + 1), SotClipboardFormatId::STRING
);
404 nType
= XTYP_EXECUTE
;
407 long DdeConnection::GetError()
409 return pImp
->nStatus
;
412 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */