home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
ool.zip
/
OOL
/
source
/
xdde.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1997-04-05
|
14KB
|
499 lines
#include "XWindow.h"
#include "XDDE.h"
#include "XDefHdl.h"
#include <stdlib.h>
#include <string.h>
#include "xprocess.h"
class ddehandler:public XDefaultHandler
{
XDDE *dde;
public:
ddehandler(const XWindow * w, const XDDE * d):XDefaultHandler(w)
{
dde = (XDDE *) d;
}
BOOL HandleEvent(ULONG, void *, void *);
};
/*@
@class XDDE
@type overview
@symbol _
@remarks XDDE supports "dynamic data exchange". An instance of XDDE can be server or client,
it should be possible to create two or more XDDE∩s for one window.
See OS/2 documentation for details.
*/
/*@ XDDE :: XDDE(const XWindow * handleFor, const char *appName, const char *topicName, const BOOL s)
@group constructors/destructors
@remarks Constructs a XDDE instance
@parameters <t '°' c=2>
°XWindow * owner °the window to handle dde for. If you have set a control as a client
for a framewindow with SetClient() you must give the control as the
owner of the XDDE instance, not the frame window!
°char * appName °application name:<P>
server: the appname to distribute<BR>
client: the needed appname
°char * topicName °topic name:<P>
server: the topic to distribute<BR>
client: the needed topic
°BOOL isServer °TRUE = server is generated, FALSE = client is generated
(default is FALSE). If a server is generated XDDE will handle
all events automaticaly, for clients you must call XDDE::Init()
to get a connection to a server
</t>
*/
XDDE :: XDDE(const XWindow * handleFor, const char *appName, const char *topicName, const BOOL s)
{
isServer = s;
clients = 0;
clientList = NULL;
connected = FALSE;
topic = topicName;
app = appName;
window = (XWindow *) handleFor;
ack = 0;
handler = new ddehandler(window, this);
}
/*@ XDDE::Init()
@group connection
@remarks Initiates a connection from a client to a server.
@returns BOOL success
*/
BOOL XDDE::Init()
{
CONVCONTEXT ConvContext;
memset(&ConvContext, 0, sizeof(CONVCONTEXT));
ConvContext.cb = sizeof(CONVCONTEXT);
if (!connected)
return WinDdeInitiate(window->GetHandle(), (PSZ) app, (PSZ) topic, &ConvContext);
else
return TRUE;
}
/*@ XDDE::Terminate()
@group connection
@remarks Terminates the dde-connection
*/
void XDDE::Terminate()
{
if (connected)
{
if (isServer)
{
int i;
for (i = 0; i < clients; i++)
if (clientList[i] != 0)
WinDdePostMsg(clientList[i], window->GetHandle(), WM_DDE_TERMINATE, NULL, TRUE);
}
else
WinDdePostMsg(server, window->GetHandle(), WM_DDE_TERMINATE, NULL, TRUE);
connected = 0;
}
}
/*@ XDDE :: ~XDDE()
@group constructors/destructors
@remarks The destructor of an instance is not called automaticaly, so
don∩t forget to call this function. If a connection is established,
XDDE::Terminate() is called automaticaly
*/
XDDE :: ~XDDE()
{
if (connected)
Terminate();
delete handler;
}
BOOL ddehandler::HandleEvent(ULONG msg, MPARAM mp1, MPARAM mp2)
{
switch (msg)
{
case WM_DDE_INITIATE:
{
if (!dde->isServer)
break;
CONVCONTEXT ConvContext;
memset(&ConvContext, 0, sizeof(CONVCONTEXT));
ConvContext.cb = sizeof(CONVCONTEXT);
PDDEINIT pDdeInit = (PDDEINIT) mp2;
if (((HWND) mp1 != dde->window->GetHandle()) && !strcmp((char *) pDdeInit->pszAppName, (char*) dde->app) && !strcmp((char *) pDdeInit->pszTopic, (char*) dde->topic))
{
SHORT i;
for (i = 0; i < dde->clients; i++)
if (dde->clientList[i] == (HWND) mp1)
return FALSE;
dde->clients += 1;
dde->clientList = (ULONG *) realloc(dde->clientList, dde->clients * 4);
dde->clientList[dde->clients - 1] = (HWND) mp1;
dde->connected = TRUE;
WinDdeRespond((HWND) mp1, dde->window->GetHandle(), (PSZ) dde->app, (PSZ) dde->topic, &ConvContext);
dde->Connected((HWND) mp1);
return TRUE;
}
}
break;
case WM_DDE_INITIATEACK:
{
PDDEINIT pDdeInit = (PDDEINIT) mp2;
if (((HWND) mp1 != dde->window->GetHandle()) && (!dde->connected))
{
if (dde->InitPossible((char *) pDdeInit->pszAppName, (char *) pDdeInit->pszTopic) == TRUE)
{
dde->server = (HWND) mp1;
dde->connected = TRUE;
dde->Connected((HWND) mp1);
DosFreeMem(mp2);
}
else
WinDdePostMsg((HWND) mp1, dde->window->GetHandle(), WM_DDE_TERMINATE, NULL, FALSE);
return TRUE;
}
}
break;
case WM_DDE_REQUEST:
{
HWND client = (HWND) mp1;
PDDESTRUCT pDdeStruct = (PDDESTRUCT) mp2;
dde->DataRequested((char *) DDES_PSZITEMNAME(pDdeStruct), pDdeStruct->usFormat, client);
}
break;
case WM_DDE_ADVISE:
{
HWND client = (HWND) mp1;
PDDESTRUCT pDdeStruct = (PDDESTRUCT) mp2;
dde->AdviseRequested((char *) DDES_PSZITEMNAME(pDdeStruct), pDdeStruct->usFormat, client);
}
break;
case WM_DDE_UNADVISE:
{
HWND client = (HWND) mp1;
dde->UnAdviseRequested(client);
}
break;
case WM_DDE_DATA:
{
PDDESTRUCT pDdeStruct = (PDDESTRUCT) mp2;
if (dde->server != (HWND) mp1)
return FALSE;
DosGetSharedMem(pDdeStruct, PAG_READ | PAG_WRITE);
dde->DataReceived(pDdeStruct->cbData, DDES_PABDATA(pDdeStruct), (char *) DDES_PSZITEMNAME(pDdeStruct), pDdeStruct->usFormat);
}
break;
case WM_DDE_ACK:
{
PDDESTRUCT pDdeStruct = (PDDESTRUCT) mp2;
if (dde->server != (HWND) mp1)
return FALSE;
if (pDdeStruct)
{
dde->ack = pDdeStruct->fsStatus;
DosFreeMem(pDdeStruct);
}
dde->Acknowledgement(dde->ack);
return TRUE;
}
break;
case WM_DDE_TERMINATE:
{
if (dde->connected)
{
WinDdePostMsg(dde->server, dde->window->GetHandle(), WM_DDE_TERMINATE, NULL, FALSE);
if (dde->isServer)
{
BOOL connect = FALSE;
int i;
for (i = 0; i < dde->clients; i++)
{
if (dde->clientList[i] == (HWND) mp1)
dde->clientList[i] = 0;
if (dde->clientList[i] != 0)
connect = TRUE;
}
dde->connected = connect;
if (connect == FALSE)
dde->DisConnected();
}
else
{
dde->connected = FALSE;
dde->DisConnected();
}
}
}
break;
}
return FALSE;
}
/*@ XDDE::Advise(const char *itemName, const SHORT format)
@group data exchange
@remarks Calls the server to establish a continous data-exchange
@parameters char * itemName the name of the requested item<BR>
SHORT format needed format of data
*/
BOOL XDDE::Advise(const char *itemName, const SHORT format)
{
PDDESTRUCT pDdeStruct;
if (!connected)
return FALSE;
pDdeStruct = MakeDDEMsg(format, itemName, NULL, 0);
pDdeStruct->fsStatus |= DDE_FACKREQ;
return WinDdePostMsg(server, window->GetHandle(), WM_DDE_ADVISE, pDdeStruct, TRUE);
}
/*@ XDDE::UnAdvise(const char *itemName)
@group data exchange
@remarks Calls the server to stop continous data-exchange
@parameters char * itemName the name of the requested item
@returns BOOL success
*/
BOOL XDDE::UnAdvise(const char *itemName)
{
PDDESTRUCT pDdeStruct;
if (!connected)
return FALSE;
pDdeStruct = MakeDDEMsg(0, itemName, NULL, 0); // DDEFMT_TEXT
return WinDdePostMsg(server, window->GetHandle(), WM_DDE_UNADVISE, pDdeStruct, TRUE);
}
/*@ XDDE::GetData(const char *itemName, const SHORT format)
@group data exchange
@remarks Calls the server send data one time
@parameters char * itemName the name of the requested item<BR>
SHORT format needed format of data
*/
BOOL XDDE::GetData(const char *itemName, const SHORT format)
{
PDDESTRUCT pDdeStruct;
if (!connected)
return FALSE;
pDdeStruct = MakeDDEMsg(format, itemName, NULL, 0); // DDEFMT_TEXT
return WinDdePostMsg(server, window->GetHandle(), WM_DDE_REQUEST, pDdeStruct, TRUE);
}
/*@ XDDE::SendCommand(const char *itemName, const char *theCommand)
@group data exchange
@remarks Send a command
@parameters char * itemName the name of the requested item<BR>
char * command command to execute
*/
BOOL XDDE::SendCommand(const char *itemName, const char *theCommand)
{
char command[200];
PDDESTRUCT pDdeStruct;
if (!connected)
return FALSE;
memcpy((char *) command, theCommand, strlen(theCommand) + 1);
pDdeStruct = MakeDDEMsg(DDEFMT_TEXT, itemName, &command, sizeof(command));
return WinDdePostMsg(server, window->GetHandle(), WM_DDE_EXECUTE, pDdeStruct, TRUE);
}
/*@ XDDE::PokeData(const OOL_WINDOWHANDLE handle, const char *itemName, const void *data, const ULONG s, const SHORT format)
@group data exchange
@remarks Poke data
@parameters <t '°' c=2>
°OOL_WINDOWHANDLE °handle of the receiver
°char * itemName °the name of the requested item
°void * data °buffer which holds data
°ULONG size °size of the buffer
°SHORT format °format of the data (default is DDEF_TEXT)
</t>
*/
BOOL XDDE::PokeData(const OOL_WINDOWHANDLE handle, const char *itemName, const void *data, const ULONG s, const SHORT format)
{
PDDESTRUCT pDdeStruct;
ULONG size = s;
if (!connected)
return FALSE;
if (size == 0)
{
if (format == DDEFMT_TEXT)
size = strlen((char *) data) + 1;
else
return FALSE;
}
pDdeStruct = MakeDDEMsg(format, itemName, data, size); // DDEFMT_TEXT
return WinDdePostMsg(handle, window->GetHandle(), WM_DDE_POKE, pDdeStruct, TRUE);
}
/*@ XDDE::SendData(const OOL_WINDOWHANDLE client, const char *itemName, const void *data, const ULONG s, const SHORT format)
@group data exchange
@remarks Send data to a client
@parameters <t '°' c=2>
°OOL_WINDOWHANDLE °handle of the receiver
°char * itemName °the name of the requested item
°void * data °buffer which holds data
°ULONG size °size of the buffer
°SHORT format °format of the data (default is DDEF_TEXT)
</t>
*/
BOOL XDDE::SendData(const OOL_WINDOWHANDLE client, const char *itemName, const void *data, const ULONG s, const SHORT format)
{
PDDESTRUCT pDdeStruct;
ULONG size = s;
if (!connected)
return FALSE;
if (size == 0)
{
if (format == DDEFMT_TEXT)
size = strlen((char *) data) + 1;
else
return FALSE;
}
pDdeStruct = MakeDDEMsg(format, itemName, data, size); // DDEFMT_TEXT
PID pid;
TID tid;
WinQueryWindowProcess(client, &pid, &tid);
DosGiveSharedMem(&pDdeStruct, pid, PAG_READ | PAG_WRITE);
return WinDdePostMsg(client, window->GetHandle(), WM_DDE_DATA, pDdeStruct, TRUE);
}
PDDESTRUCT XDDE::MakeDDEMsg(const USHORT usFormat, const char *itemName, const void *Data, const USHORT usDataSize)
{
PDDESTRUCT pdde = (PDDESTRUCT) 0;
ULONG rc = 0;
ULONG usSegSize;
ULONG totalsize;
usSegSize = strlen(itemName) + 1;
totalsize = sizeof(DDESTRUCT) + usDataSize + usSegSize;
rc = DosAllocSharedMem((PPVOID) & pdde, (PSZ) 0, totalsize,
PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE
| OBJ_GIVEABLE | OBJ_GETTABLE);
if (rc)
return ((PDDESTRUCT) 0);
memset((PVOID) pdde, 0, (size_t) usSegSize);
pdde->usFormat = usFormat;
pdde->offszItemName = (USHORT) sizeof(DDESTRUCT);
memcpy(DDES_PSZITEMNAME(pdde), itemName, usSegSize);
pdde->offabData = (USHORT) sizeof(DDESTRUCT) + usSegSize;
memcpy(DDES_PABDATA(pdde), Data, usDataSize);
pdde->fsStatus = 0;
pdde->cbData = (ULONG) totalsize;
return pdde;
}
/////////////////docs only
/*@ XDDE::AdviseRequested()
@group application notification
@remarks Informs a server that an advise is requested. Override this
function if you need this information.
@parameters <t '°' c=2>
°char * itemName °the name of the requested item
°SHORT format °format of the data
°OOL_WINDOWHANDLE °handle of the client
</t>
*/
/*@ XDDE::Connected()
@group application notification
@remarks Informs a server that a client has been connected. Override this
function if you need this information.
@parameters OOL_WINDOWHANDLE handle of the client
*/
/*@ XDDE::DataReceived()
@group application notification
@remarks Informs that datas has been received. Override this
function if you need this information.
@parameters <t '°' c=2>
°ULONG size °size of the data
°void * data °buffer which holds the data
°char * itemName °item name
°SHORT format °format of the data
</t>
*/
/*@ XDDE::DataRequested()
@group application notification
@remarks Informs a server that datas are needed. Override this
function if you need this information.
@parameters <t '°' c=2>
°char * itemName °item name
°SHORT format °format of the data
°OOL_WINDOWHANDLE °the clients handle
</t>
*/
/*@ XDDE::DisConnected()
@group application notification
@remarks Informs that the xdde-instance has no more connections. Override this
function if you need this information.
*/
/*@ XDDE::QueryOwner()
@group misc
@remarks Returns a pointer to the owner window
@returns XWindow * the owner
*/
/*@ XDDE::IsConnected()
@group misc
@remarks Returns if a connection is established or not
@returns BOOL connected
*/
/*@ XDDE::InitPossible(char*, char*)
@group connect
@remarks Informs the application that a server is ready for a DDE connect. Return TRUE for a connect, otherwise return FALSE.
On default this function returns allways TRUE, you must override this function to code the behaviour you want.
@parameters char * appName applivcation name of the possible server<BR>
char * toppicname toppic-name that the possible server supports
@returns BOOL connect
*/