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 // --- DdeInternat::CliCallback() ----------------------------------
57 HDDEDATA CALLBACK
DdeInternal::CliCallback( WORD nCode
, WORD nCbType
,
58 HCONV hConv
, HSZ
, HSZ hText2
,
59 HDDEDATA hData
, DWORD nInfo1
, DWORD
)
61 HDDEDATA nRet
= DDE_FNOTPROCESSED
;
62 const std::vector
<DdeConnection
*> &rAll
= DdeConnection::GetConnections();
63 DdeConnection
* self
= 0;
65 DdeInstData
* pInst
= ImpGetInstData();
66 DBG_ASSERT(pInst
,"SVDDE:No instance data");
68 for ( size_t i
= 0; i
< rAll
.size(); ++i
)
72 if ( self
->pImp
->hConv
== hConv
)
79 std::vector
<DdeTransaction
*>::iterator iter
;
80 for( iter
= self
->aTransactions
.begin(); iter
!= self
->aTransactions
.end(); ++iter
)
84 case XTYP_XACT_COMPLETE
:
85 if( (DWORD
)(*iter
)->nId
== nInfo1
)
87 nCode
= (*iter
)->nType
& (XCLASS_MASK
| XTYP_MASK
);
88 (*iter
)->bBusy
= false;
89 (*iter
)->Done( 0 != hData
);
95 self
->pImp
->hConv
= DdeReconnect( hConv
);
96 self
->pImp
->nStatus
= self
->pImp
->hConv
98 : DdeGetLastError( pInst
->hDdeInstCli
);
99 iter
= self
->aTransactions
.end();
105 bFound
= *(*iter
)->pName
== hText2
;
112 if( iter
!= self
->aTransactions
.end() )
119 static_cast<DdeLink
*>(*iter
)->Notify();
120 nRet
= (HDDEDATA
)DDE_FACK
;
126 if( !hData
&& XTYP_REQUEST
== nCode
)
132 d
.pImp
->hData
= hData
;
133 d
.pImp
->nFmt
= DdeData::GetInternalFormat( nCbType
);
136 nRet
= (HDDEDATA
)DDE_FACK
;
144 // --- DdeConnection::DdeConnection() ------------------------------
146 DdeConnection::DdeConnection( const OUString
& rService
, const OUString
& rTopic
)
149 pImp
->nStatus
= DMLERR_NO_ERROR
;
152 DdeInstData
* pInst
= ImpGetInstData();
154 pInst
= ImpInitInstData();
156 pInst
->nInstanceCli
++;
157 if ( !pInst
->hDdeInstCli
)
159 pImp
->nStatus
= DdeInitialize( &pInst
->hDdeInstCli
,
160 (PFNCALLBACK
)DdeInternal::CliCallback
,
161 APPCLASS_STANDARD
| APPCMD_CLIENTONLY
|
162 CBF_FAIL_ALLSVRXACTIONS
|
163 CBF_SKIP_REGISTRATIONS
|
164 CBF_SKIP_UNREGISTRATIONS
, 0L );
167 pService
= new DdeString( pInst
->hDdeInstCli
, rService
);
168 pTopic
= new DdeString( pInst
->hDdeInstCli
, rTopic
);
170 if ( pImp
->nStatus
== DMLERR_NO_ERROR
)
172 pImp
->hConv
= DdeConnect( pInst
->hDdeInstCli
,*pService
,*pTopic
, NULL
);
174 pImp
->nStatus
= DdeGetLastError( pInst
->hDdeInstCli
);
177 pInst
->aConnections
.push_back( this );
180 // --- DdeConnection::~DdeConnection() -----------------------------
182 DdeConnection::~DdeConnection()
185 DdeDisconnect( pImp
->hConv
);
190 DdeInstData
* pInst
= ImpGetInstData();
191 DBG_ASSERT(pInst
,"SVDDE:No instance data");
193 std::vector
<DdeConnection
*>::iterator
it(std::find(pInst
->aConnections
.begin(),
194 pInst
->aConnections
.end(),
196 if (it
!= pInst
->aConnections
.end())
197 pInst
->aConnections
.erase(it
);
199 pInst
->nInstanceCli
--;
201 if ( !pInst
->nInstanceCli
&& pInst
->hDdeInstCli
)
203 if( DdeUninitialize( pInst
->hDdeInstCli
) )
205 pInst
->hDdeInstCli
= 0;
206 if( pInst
->nRefCount
== 0 )
213 // --- DdeConnection::IsConnected() --------------------------------
215 bool DdeConnection::IsConnected()
219 if ( DdeQueryConvInfo( pImp
->hConv
, QID_SYNC
, &c
) )
223 DdeInstData
* pInst
= ImpGetInstData();
224 pImp
->hConv
= DdeReconnect( pImp
->hConv
);
225 pImp
->nStatus
= pImp
->hConv
? DMLERR_NO_ERROR
: DdeGetLastError( pInst
->hDdeInstCli
);
226 return pImp
->nStatus
== DMLERR_NO_ERROR
;
230 // --- DdeConnection::GetServiceName() -----------------------------
232 const OUString
DdeConnection::GetServiceName()
234 return pService
->toOUString();
237 // --- DdeConnection::GetTopicName() -------------------------------
239 const OUString
DdeConnection::GetTopicName()
241 return pTopic
->toOUString();
244 // --- DdeConnection::GetConvId() ----------------------------------
246 sal_IntPtr
DdeConnection::GetConvId()
248 return (sal_IntPtr
)pImp
->hConv
;
251 const std::vector
<DdeConnection
*>& DdeConnection::GetConnections()
253 DdeInstData
* pInst
= ImpGetInstData();
254 DBG_ASSERT(pInst
,"SVDDE:No instance data");
255 return pInst
->aConnections
;
258 // --- DdeTransaction::DdeTransaction() ----------------------------
260 DdeTransaction::DdeTransaction( DdeConnection
& d
, const OUString
& rItemName
,
264 DdeInstData
* pInst
= ImpGetInstData();
265 pName
= new DdeString( pInst
->hDdeInstCli
, rItemName
);
271 rDde
.aTransactions
.push_back( this );
274 // --- DdeTransaction::~DdeTransaction() ---------------------------
276 DdeTransaction::~DdeTransaction()
278 if ( nId
&& rDde
.pImp
->hConv
)
280 DdeInstData
* pInst
= ImpGetInstData();
281 DdeAbandonTransaction( pInst
->hDdeInstCli
, rDde
.pImp
->hConv
, nId
);
285 rDde
.aTransactions
.erase(std::remove(rDde
.aTransactions
.begin(),
286 rDde
.aTransactions
.end(),this));
289 // --- DdeTransaction::Execute() -----------------------------------
291 void DdeTransaction::Execute()
294 void* pData
= (void*)(const void *)aDdeData
;
295 DWORD nData
= (DWORD
)(long)aDdeData
;
296 sal_uLong nIntFmt
= aDdeData
.pImp
->nFmt
;
297 UINT nExtFmt
= DdeData::GetExternalFormat( nIntFmt
);
298 DdeInstData
* pInst
= ImpGetInstData();
300 if ( nType
== XTYP_EXECUTE
)
302 if ( nType
!= XTYP_EXECUTE
&& nType
!= XTYP_POKE
)
309 HDDEDATA hData
= DdeClientTransaction( (unsigned char*)pData
,
310 nData
, rDde
.pImp
->hConv
,
311 hItem
, nExtFmt
, (UINT
)nType
,
312 (DWORD
)nTime
, (DWORD FAR
*)NULL
);
314 rDde
.pImp
->nStatus
= DdeGetLastError( pInst
->hDdeInstCli
);
315 if( hData
&& nType
== XTYP_REQUEST
)
319 d
.pImp
->hData
= hData
;
320 d
.pImp
->nFmt
= nIntFmt
;
324 DdeFreeDataHandle( hData
);
329 if ( nId
&& rDde
.pImp
->hConv
)
330 DdeAbandonTransaction( pInst
->hDdeInstCli
, rDde
.pImp
->hConv
, nId
);
333 HDDEDATA hRet
= DdeClientTransaction( (unsigned char*)pData
, nData
,
334 rDde
.pImp
->hConv
, hItem
, nExtFmt
,
335 (UINT
)nType
, TIMEOUT_ASYNC
,
336 (DWORD FAR
*) ((long*) &nId
) );
337 rDde
.pImp
->nStatus
= hRet
? DMLERR_NO_ERROR
338 : DdeGetLastError( pInst
->hDdeInstCli
);
342 // --- DdeTransaction::GetName() -----------------------------------
344 const OUString
DdeTransaction::GetName() const
346 return pName
->toOUString();
349 // --- DdeTransaction::Data() --------------------------------------
352 void DdeTransaction::Data( const DdeData
* p
)
354 if ( ::tools::SolarMutex::Acquire() )
356 aData
.Call( (void*)p
);
357 ::tools::SolarMutex::Release();
361 // --- DdeTransaction::Done() --------------------------------------
363 void DdeTransaction::Done( bool bDataValid
)
365 const sal_uIntPtr
nDataValid(bDataValid
);
366 aDone
.Call( reinterpret_cast<void*>(nDataValid
) );
369 // --- DdeLink::DdeLink() ------------------------------------------
371 DdeLink::DdeLink( DdeConnection
& d
, const OUString
& aItemName
, long n
)
372 : DdeTransaction (d
, aItemName
, n
)
376 // --- DdeLink::~DdeLink() -----------------------------------------
380 nType
= (sal_uInt16
)XTYP_ADVSTOP
;
384 // --- DdeLink::Notify() -----------------------------------------
386 void DdeLink::Notify()
388 aNotify
.Call( NULL
);
391 // --- DdeRequest::DdeRequest() ------------------------------------
393 DdeRequest::DdeRequest( DdeConnection
& d
, const OUString
& i
, long n
)
394 : DdeTransaction( d
, i
, n
)
396 nType
= XTYP_REQUEST
;
399 // --- DdeWarmLink::DdeWarmLink() ----------------------------------
401 DdeWarmLink::DdeWarmLink( DdeConnection
& d
, const OUString
& i
, long n
)
404 nType
= XTYP_ADVSTART
| XTYPF_NODATA
;
407 // --- DdeHotLink::DdeHotLink() ------------------------------------
409 DdeHotLink::DdeHotLink( DdeConnection
& d
, const OUString
& i
, long n
)
412 nType
= XTYP_ADVSTART
;
415 // --- DdePoke::DdePoke() ------------------------------------------
417 DdePoke::DdePoke( DdeConnection
& d
, const OUString
& i
, const char* p
,
418 long l
, sal_uLong f
, long n
)
419 : DdeTransaction( d
, i
, n
)
421 aDdeData
= DdeData( p
, l
, f
);
425 // --- DdePoke::DdePoke() ------------------------------------------
427 DdePoke::DdePoke( DdeConnection
& d
, const OUString
& i
, const OUString
& rData
,
429 : DdeTransaction( d
, i
, n
)
431 aDdeData
= DdeData( (void*) rData
.getStr(), sizeof(sal_Unicode
) * (rData
.getLength()), CF_TEXT
);
435 // --- DdePoke::DdePoke() ------------------------------------------
437 DdePoke::DdePoke( DdeConnection
& d
, const OUString
& i
, const DdeData
& rData
,
439 : DdeTransaction( d
, i
, n
)
445 // --- DdeExecute::DdeExecute() ------------------------------------
447 DdeExecute::DdeExecute( DdeConnection
& d
, const OUString
& rData
, long n
)
448 : DdeTransaction( d
, OUString(), n
)
450 aDdeData
= DdeData( (void*)rData
.getStr(), sizeof(sal_Unicode
) * (rData
.getLength() + 1), CF_TEXT
);
451 nType
= XTYP_EXECUTE
;
454 // --- DdeConnection::GetError() -----------------------------------
456 long DdeConnection::GetError()
458 return pImp
->nStatus
;
461 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */