blob: 71e719f0c9727943ac257d04deaba8d0f7af1f21 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svl.hxx"
#define UNICODE
#include <string.h> // memset
#include "ddeimp.hxx"
#include <svl/svdde.hxx>
#include <osl/thread.h>
#include <tools/debug.hxx>
#include <tools/solarmutex.hxx>
#include <vos/mutex.hxx>
// static DWORD hDdeInst = NULL;
// static short nInstance = 0;
// DdeConnections* DdeConnection::pConnections = NULL;
DdeInstData* ImpInitInstData()
{
DdeInstData* pData = new DdeInstData;
memset( pData,0,sizeof(DdeInstData) );
DdeInstData** ppInst = (DdeInstData**)GetAppData( SHL_SVDDE );
*ppInst = pData;
return pData;
}
void ImpDeinitInstData()
{
DdeInstData** ppInst = (DdeInstData**)GetAppData( SHL_SVDDE );
delete (*ppInst);
*ppInst = 0;
}
struct DdeImp
{
HCONV hConv;
long nStatus;
};
// --- DdeInternat::CliCallback() ----------------------------------
HDDEDATA CALLBACK DdeInternal::CliCallback(
WORD nCode, WORD nCbType, HCONV hConv, HSZ, HSZ hText2,
HDDEDATA hData, DWORD nInfo1, DWORD )
{
HDDEDATA nRet = DDE_FNOTPROCESSED;
DdeConnections& rAll = (DdeConnections&)DdeConnection::GetConnections();
DdeConnection* self = 0;
DdeInstData* pInst = ImpGetInstData();
DBG_ASSERT(pInst,"SVDDE:No instance data");
for ( self = rAll.First(); self; self = rAll.Next() )
if ( self->pImp->hConv == hConv )
break;
if( self )
{
DdeTransaction* t;
sal_Bool bFound = sal_False;
for( t = self->aTransactions.First(); t; t = self->aTransactions.Next() )
{
switch( nCode )
{
case XTYP_XACT_COMPLETE:
if( (DWORD)t->nId == nInfo1 )
{
nCode = t->nType & (XCLASS_MASK | XTYP_MASK);
t->bBusy = sal_False;
t->Done( 0 != hData );
bFound = sal_True;
}
break;
case XTYP_DISCONNECT:
self->pImp->hConv = DdeReconnect( hConv );
self->pImp->nStatus = self->pImp->hConv
? DMLERR_NO_ERROR
: DdeGetLastError( pInst->hDdeInstCli );
t = 0;
nRet = 0;
bFound = sal_True;
break;
case XTYP_ADVDATA:
bFound = sal_Bool( *t->pName == hText2 );
break;
}
if( bFound )
break;
}
if( t )
{
switch( nCode )
{
case XTYP_ADVDATA:
if( !hData )
{
((DdeLink*) t)->Notify();
nRet = (HDDEDATA)DDE_FACK;
break;
}
// kein break;
case XTYP_REQUEST:
if( !hData && XTYP_REQUEST == nCode )
{
}
DdeData d;
d.pImp->hData = hData;
d.pImp->nFmt = DdeData::GetInternalFormat( nCbType );
d.Lock();
t->Data( &d );
nRet = (HDDEDATA)DDE_FACK;
break;
}
}
}
return nRet;
}
// --- DdeConnection::DdeConnection() ------------------------------
DdeConnection::DdeConnection( const String& rService, const String& rTopic )
{
pImp = new DdeImp;
pImp->nStatus = DMLERR_NO_ERROR;
pImp->hConv = NULL;
DdeInstData* pInst = ImpGetInstData();
if( !pInst )
pInst = ImpInitInstData();
pInst->nRefCount++;
pInst->nInstanceCli++;
if ( !pInst->hDdeInstCli )
{
pImp->nStatus = DdeInitialize( &pInst->hDdeInstCli,
(PFNCALLBACK)DdeInternal::CliCallback,
APPCLASS_STANDARD | APPCMD_CLIENTONLY |
CBF_FAIL_ALLSVRXACTIONS |
CBF_SKIP_REGISTRATIONS |
CBF_SKIP_UNREGISTRATIONS, 0L );
pInst->pConnections = new DdeConnections;
}
pService = new DdeString( pInst->hDdeInstCli, rService );
pTopic = new DdeString( pInst->hDdeInstCli, rTopic );
if ( pImp->nStatus == DMLERR_NO_ERROR )
{
pImp->hConv = DdeConnect( pInst->hDdeInstCli,*pService,*pTopic, NULL);
if( !pImp->hConv )
pImp->nStatus = DdeGetLastError( pInst->hDdeInstCli );
}
if ( pInst->pConnections )
pInst->pConnections->Insert( this );
}
// --- DdeConnection::~DdeConnection() -----------------------------
DdeConnection::~DdeConnection()
{
if ( pImp->hConv )
DdeDisconnect( pImp->hConv );
delete pService;
delete pTopic;
DdeInstData* pInst = ImpGetInstData();
DBG_ASSERT(pInst,"SVDDE:No instance data");
if ( pInst->pConnections )
pInst->pConnections->Remove( this );
pInst->nInstanceCli--;
pInst->nRefCount--;
if ( !pInst->nInstanceCli && pInst->hDdeInstCli )
{
if( DdeUninitialize( pInst->hDdeInstCli ) )
{
pInst->hDdeInstCli = NULL;
delete pInst->pConnections;
pInst->pConnections = NULL;
if( pInst->nRefCount == 0 )
ImpDeinitInstData();
}
}
delete pImp;
}
// --- DdeConnection::IsConnected() --------------------------------
sal_Bool DdeConnection::IsConnected()
{
CONVINFO c;
#ifdef OS2
c.nSize = sizeof( c );
#else
c.cb = sizeof( c );
#endif
if ( DdeQueryConvInfo( pImp->hConv, QID_SYNC, &c ) )
return sal_True;
else
{
DdeInstData* pInst = ImpGetInstData();
pImp->hConv = DdeReconnect( pImp->hConv );
pImp->nStatus = pImp->hConv ? DMLERR_NO_ERROR : DdeGetLastError( pInst->hDdeInstCli );
return sal_Bool( pImp->nStatus == DMLERR_NO_ERROR );
}
}
// --- DdeConnection::GetServiceName() -----------------------------
const String& DdeConnection::GetServiceName()
{
return (const String&)*pService;
}
// --- DdeConnection::GetTopicName() -------------------------------
const String& DdeConnection::GetTopicName()
{
return (const String&)*pTopic;
}
// --- DdeConnection::GetConvId() ----------------------------------
long DdeConnection::GetConvId()
{
return (long)pImp->hConv;
}
const DdeConnections& DdeConnection::GetConnections()
{
DdeInstData* pInst = ImpGetInstData();
DBG_ASSERT(pInst,"SVDDE:No instance data");
return *(pInst->pConnections);
}
// --- DdeTransaction::DdeTransaction() ----------------------------
DdeTransaction::DdeTransaction( DdeConnection& d, const String& rItemName,
long n ) :
rDde( d )
{
DdeInstData* pInst = ImpGetInstData();
pName = new DdeString( pInst->hDdeInstCli, rItemName );
nTime = n;
nId = 0;
nType = 0;
bBusy = sal_False;
rDde.aTransactions.Insert( this );
}
// --- DdeTransaction::~DdeTransaction() ---------------------------
DdeTransaction::~DdeTransaction()
{
if ( nId && rDde.pImp->hConv )
{
DdeInstData* pInst = ImpGetInstData();
DdeAbandonTransaction( pInst->hDdeInstCli, rDde.pImp->hConv, nId );
}
delete pName;
rDde.aTransactions.Remove( this );
}
// --- DdeTransaction::Execute() -----------------------------------
void DdeTransaction::Execute()
{
HSZ hItem = *pName;
void* pData = (void*)(const void *)aDdeData;
DWORD nData = (DWORD)(long)aDdeData;
sal_uLong nIntFmt = aDdeData.pImp->nFmt;
UINT nExtFmt = DdeData::GetExternalFormat( nIntFmt );
DdeInstData* pInst = ImpGetInstData();
if ( nType == XTYP_EXECUTE )
hItem = NULL;
if ( nType != XTYP_EXECUTE && nType != XTYP_POKE )
{
pData = NULL;
nData = 0L;
}
if ( nTime )
{
HDDEDATA hData = DdeClientTransaction( (unsigned char*)pData,
nData, rDde.pImp->hConv,
hItem, nExtFmt, (UINT)nType,
(DWORD)nTime, (DWORD FAR*)NULL );
rDde.pImp->nStatus = DdeGetLastError( pInst->hDdeInstCli );
if( hData && nType == XTYP_REQUEST )
{
{
DdeData d;
d.pImp->hData = hData;
d.pImp->nFmt = nIntFmt;
d.Lock();
Data( &d );
}
DdeFreeDataHandle( hData );
}
}
else
{
if ( nId && rDde.pImp->hConv )
DdeAbandonTransaction( pInst->hDdeInstCli, rDde.pImp->hConv, nId);
nId = 0;
bBusy = sal_True;
HDDEDATA hRet = DdeClientTransaction( (unsigned char*)pData, nData,
rDde.pImp->hConv, hItem, nExtFmt,
(UINT)nType, TIMEOUT_ASYNC,
(DWORD FAR *) ((long*) &nId) );
rDde.pImp->nStatus = hRet ? DMLERR_NO_ERROR
: DdeGetLastError( pInst->hDdeInstCli );
}
}
// --- DdeTransaction::GetName() -----------------------------------
const String& DdeTransaction::GetName() const
{
return *pName;
}
// --- DdeTransaction::Data() --------------------------------------
void __EXPORT DdeTransaction::Data( const DdeData* p )
{
if ( ::tools::SolarMutex::Acquire() )
{
aData.Call( (void*)p );
::tools::SolarMutex::Release();
}
}
// --- DdeTransaction::Done() --------------------------------------
void __EXPORT DdeTransaction::Done( sal_Bool bDataValid )
{
aDone.Call( (void*)bDataValid );
}
// --- DdeLink::DdeLink() ------------------------------------------
DdeLink::DdeLink( DdeConnection& d, const String& aItemName, long n ) :
DdeTransaction (d, aItemName, n)
{
}
// --- DdeLink::~DdeLink() -----------------------------------------
DdeLink::~DdeLink()
{
nType = (sal_uInt16)XTYP_ADVSTOP;
nTime = 0;
}
// --- DdeLink::Notify() -----------------------------------------
void __EXPORT DdeLink::Notify()
{
aNotify.Call( NULL );
}
// --- DdeRequest::DdeRequest() ------------------------------------
DdeRequest::DdeRequest( DdeConnection& d, const String& i, long n ) :
DdeTransaction( d, i, n )
{
nType = XTYP_REQUEST;
}
// --- DdeWarmLink::DdeWarmLink() ----------------------------------
DdeWarmLink::DdeWarmLink( DdeConnection& d, const String& i, long n ) :
DdeLink( d, i, n )
{
nType = XTYP_ADVSTART | XTYPF_NODATA;
}
// --- DdeHotLink::DdeHotLink() ------------------------------------
DdeHotLink::DdeHotLink( DdeConnection& d, const String& i, long n ) :
DdeLink( d, i, n )
{
nType = XTYP_ADVSTART;
}
// --- DdePoke::DdePoke() ------------------------------------------
DdePoke::DdePoke( DdeConnection& d, const String& i, const char* p,
long l, sal_uLong f, long n ) :
DdeTransaction( d, i, n )
{
aDdeData = DdeData( p, l, f );
nType = XTYP_POKE;
}
// --- DdePoke::DdePoke() ------------------------------------------
DdePoke::DdePoke( DdeConnection& d, const String& i, const String& rData,
long n ) :
DdeTransaction( d, i, n )
{
// ByteString aByteStr( rData, osl_getThreadTextEncoding() );
aDdeData = DdeData( (void*) rData.GetBuffer(), sizeof(sal_Unicode) * (rData.Len()), CF_TEXT );
nType = XTYP_POKE;
}
// --- DdePoke::DdePoke() ------------------------------------------
DdePoke::DdePoke( DdeConnection& d, const String& i, const DdeData& rData,
long n ) :
DdeTransaction( d, i, n )
{
aDdeData = rData;
nType = XTYP_POKE;
}
// --- DdeExecute::DdeExecute() ------------------------------------
DdeExecute::DdeExecute( DdeConnection& d, const String& rData, long n ) :
DdeTransaction( d, String(), n )
{
// ByteString aByteStr( rData, osl_getThreadTextEncoding() );
aDdeData = DdeData( (void*)rData.GetBuffer(), sizeof(sal_Unicode) * (rData.Len() + 1), CF_TEXT );
nType = XTYP_EXECUTE;
}
// --- DdeConnection::GetError() -----------------------------------
long DdeConnection::GetError()
{
return pImp->nStatus;
}