bump product version to 4.2.0.1
[LibreOffice.git] / svl / source / svdde / ddecli.cxx
blob96cf5f38be4e191b548fc97b6681998aede45e71
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 <string.h>
23 #include <algorithm>
24 #include "ddeimp.hxx"
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 );
37 *ppInst = pData;
38 return pData;
41 void ImpDeinitInstData()
43 DdeInstData** ppInst = (DdeInstData**)GetAppData( SHL_SVDDE );
44 delete (*ppInst);
45 *ppInst = 0;
49 struct DdeImp
51 HCONV hConv;
52 long nStatus;
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)
70 self = rAll[i];
72 if ( self->pImp->hConv == hConv )
73 break;
76 if( self )
78 bool bFound = false;
79 std::vector<DdeTransaction*>::iterator iter;
80 for( iter = self->aTransactions.begin(); iter != self->aTransactions.end(); ++iter )
82 switch( nCode )
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 );
90 bFound = true;
92 break;
94 case XTYP_DISCONNECT:
95 self->pImp->hConv = DdeReconnect( hConv );
96 self->pImp->nStatus = self->pImp->hConv
97 ? DMLERR_NO_ERROR
98 : DdeGetLastError( pInst->hDdeInstCli );
99 iter = self->aTransactions.end();
100 nRet = 0;
101 bFound = true;
102 break;
104 case XTYP_ADVDATA:
105 bFound = *(*iter)->pName == hText2;
106 break;
108 if( bFound )
109 break;
112 if( iter != self->aTransactions.end() )
114 switch( nCode )
116 case XTYP_ADVDATA:
117 if( !hData )
119 static_cast<DdeLink*>(*iter)->Notify();
120 nRet = (HDDEDATA)DDE_FACK;
121 break;
123 // kein break;
125 case XTYP_REQUEST:
126 if( !hData && XTYP_REQUEST == nCode )
131 DdeData d;
132 d.pImp->hData = hData;
133 d.pImp->nFmt = DdeData::GetInternalFormat( nCbType );
134 d.Lock();
135 (*iter)->Data( &d );
136 nRet = (HDDEDATA)DDE_FACK;
137 break;
141 return nRet;
144 // --- DdeConnection::DdeConnection() ------------------------------
146 DdeConnection::DdeConnection( const OUString& rService, const OUString& rTopic )
148 pImp = new DdeImp;
149 pImp->nStatus = DMLERR_NO_ERROR;
150 pImp->hConv = NULL;
152 DdeInstData* pInst = ImpGetInstData();
153 if( !pInst )
154 pInst = ImpInitInstData();
155 pInst->nRefCount++;
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);
173 if( !pImp->hConv )
174 pImp->nStatus = DdeGetLastError( pInst->hDdeInstCli );
177 pInst->aConnections.push_back( this );
180 // --- DdeConnection::~DdeConnection() -----------------------------
182 DdeConnection::~DdeConnection()
184 if ( pImp->hConv )
185 DdeDisconnect( pImp->hConv );
187 delete pService;
188 delete pTopic;
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(),
195 this));
196 if (it != pInst->aConnections.end())
197 pInst->aConnections.erase(it);
199 pInst->nInstanceCli--;
200 pInst->nRefCount--;
201 if ( !pInst->nInstanceCli && pInst->hDdeInstCli )
203 if( DdeUninitialize( pInst->hDdeInstCli ) )
205 pInst->hDdeInstCli = 0;
206 if( pInst->nRefCount == 0 )
207 ImpDeinitInstData();
210 delete pImp;
213 // --- DdeConnection::IsConnected() --------------------------------
215 bool DdeConnection::IsConnected()
217 CONVINFO c;
218 c.cb = sizeof( c );
219 if ( DdeQueryConvInfo( pImp->hConv, QID_SYNC, &c ) )
220 return true;
221 else
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,
261 long n )
262 : rDde( d )
264 DdeInstData* pInst = ImpGetInstData();
265 pName = new DdeString( pInst->hDdeInstCli, rItemName );
266 nTime = n;
267 nId = 0;
268 nType = 0;
269 bBusy = false;
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 );
284 delete pName;
285 rDde.aTransactions.erase(std::remove(rDde.aTransactions.begin(),
286 rDde.aTransactions.end(),this));
289 // --- DdeTransaction::Execute() -----------------------------------
291 void DdeTransaction::Execute()
293 HSZ hItem = *pName;
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 )
301 hItem = NULL;
302 if ( nType != XTYP_EXECUTE && nType != XTYP_POKE )
304 pData = NULL;
305 nData = 0L;
307 if ( nTime )
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 )
318 DdeData d;
319 d.pImp->hData = hData;
320 d.pImp->nFmt = nIntFmt;
321 d.Lock();
322 Data( &d );
324 DdeFreeDataHandle( hData );
327 else
329 if ( nId && rDde.pImp->hConv )
330 DdeAbandonTransaction( pInst->hDdeInstCli, rDde.pImp->hConv, nId);
331 nId = 0;
332 bBusy = true;
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() -----------------------------------------
378 DdeLink::~DdeLink()
380 nType = (sal_uInt16)XTYP_ADVSTOP;
381 nTime = 0;
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 )
402 : DdeLink( d, i, n )
404 nType = XTYP_ADVSTART | XTYPF_NODATA;
407 // --- DdeHotLink::DdeHotLink() ------------------------------------
409 DdeHotLink::DdeHotLink( DdeConnection& d, const OUString& i, long n )
410 : DdeLink( d, i, 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 );
422 nType = XTYP_POKE;
425 // --- DdePoke::DdePoke() ------------------------------------------
427 DdePoke::DdePoke( DdeConnection& d, const OUString& i, const OUString& rData,
428 long n )
429 : DdeTransaction( d, i, n )
431 aDdeData = DdeData( (void*) rData.getStr(), sizeof(sal_Unicode) * (rData.getLength()), CF_TEXT );
432 nType = XTYP_POKE;
435 // --- DdePoke::DdePoke() ------------------------------------------
437 DdePoke::DdePoke( DdeConnection& d, const OUString& i, const DdeData& rData,
438 long n )
439 : DdeTransaction( d, i, n )
441 aDdeData = rData;
442 nType = XTYP_POKE;
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: */