home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ool.zip / OOL / source / xdde.cpp < prev    next >
C/C++ Source or Header  |  1997-04-05  |  14KB  |  499 lines

  1. #include "XWindow.h"
  2. #include "XDDE.h"
  3. #include "XDefHdl.h"
  4.  
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. #include "xprocess.h"
  9.  
  10. class ddehandler:public XDefaultHandler
  11. {
  12.     XDDE *dde;
  13.         public:
  14.         ddehandler(const XWindow * w, const XDDE * d):XDefaultHandler(w)
  15.     {
  16.         dde = (XDDE *) d;
  17.     }
  18.     BOOL HandleEvent(ULONG, void *, void *);
  19. };
  20.  
  21.  
  22.  
  23. /*@ 
  24. @class XDDE
  25. @type overview
  26. @symbol _
  27. @remarks XDDE supports "dynamic data exchange". An instance of XDDE can be server or client,
  28. it should be possible to create two or more XDDE∩s for one window.
  29. See OS/2 documentation for details.
  30. */
  31.  
  32.  
  33. /*@ XDDE :: XDDE(const XWindow * handleFor, const char *appName, const char *topicName, const BOOL s)
  34. @group constructors/destructors
  35. @remarks Constructs a XDDE instance
  36. @parameters <t '°' c=2>
  37.                 °XWindow * owner      °the window to handle dde for. If you have set a control as a client
  38.                                  for a framewindow with SetClient() you must give the control as the
  39.                                  owner of the XDDE instance, not the frame window!
  40.             °char * appName       °application name:<P>
  41.                                     server:   the appname to distribute<BR>
  42.                                     client:   the needed appname
  43.             °char * topicName     °topic name:<P>
  44.                                     server:   the topic to distribute<BR>
  45.                                     client:   the needed topic
  46.             °BOOL isServer        °TRUE = server is generated, FALSE = client is generated
  47.                                  (default is FALSE). If a server is generated XDDE will handle
  48.                                  all events automaticaly, for clients you must call XDDE::Init()
  49.                                  to get a connection to a server
  50.                 </t>
  51. */
  52. XDDE :: XDDE(const XWindow * handleFor, const char *appName, const char *topicName, const BOOL s)
  53. {
  54.     isServer = s;
  55.     clients = 0;
  56.     clientList = NULL;
  57.     connected = FALSE;
  58.     topic = topicName;
  59.     app = appName;
  60.     window = (XWindow *) handleFor;
  61.     ack = 0;
  62.     handler = new ddehandler(window, this);
  63. }
  64.  
  65.  
  66. /*@ XDDE::Init()
  67. @group connection
  68. @remarks Initiates a connection from a client to a server.
  69. @returns BOOL success
  70. */
  71. BOOL XDDE::Init()
  72. {
  73.     CONVCONTEXT ConvContext;
  74.  
  75.     memset(&ConvContext, 0, sizeof(CONVCONTEXT));
  76.     ConvContext.cb = sizeof(CONVCONTEXT);
  77.     if (!connected)
  78.         return WinDdeInitiate(window->GetHandle(), (PSZ) app, (PSZ) topic, &ConvContext);
  79.     else
  80.         return TRUE;
  81. }
  82.  
  83.  
  84. /*@ XDDE::Terminate()
  85. @group connection
  86. @remarks Terminates the dde-connection
  87. */
  88. void XDDE::Terminate()
  89. {
  90.     if (connected)
  91.     {
  92.         if (isServer)
  93.         {
  94.             int i;
  95.  
  96.             for (i = 0; i < clients; i++)
  97.                 if (clientList[i] != 0)
  98.                     WinDdePostMsg(clientList[i], window->GetHandle(), WM_DDE_TERMINATE, NULL, TRUE);
  99.         }
  100.         else
  101.             WinDdePostMsg(server, window->GetHandle(), WM_DDE_TERMINATE, NULL, TRUE);
  102.         connected = 0;
  103.     }
  104. }
  105.  
  106.  
  107. /*@ XDDE :: ~XDDE()
  108. @group constructors/destructors
  109. @remarks The destructor of an instance is not called automaticaly, so
  110. don∩t forget to call this function. If a connection is established,
  111. XDDE::Terminate() is called automaticaly
  112. */
  113. XDDE :: ~XDDE()
  114. {
  115.     if (connected)
  116.         Terminate();
  117.     delete handler;
  118. }
  119.  
  120.  
  121. BOOL ddehandler::HandleEvent(ULONG msg, MPARAM mp1, MPARAM mp2)
  122. {
  123.     switch (msg)
  124.     {
  125.         case WM_DDE_INITIATE:
  126.         {
  127.             if (!dde->isServer)
  128.                 break;
  129.             CONVCONTEXT ConvContext;
  130.  
  131.             memset(&ConvContext, 0, sizeof(CONVCONTEXT));
  132.             ConvContext.cb = sizeof(CONVCONTEXT);
  133.  
  134.             PDDEINIT pDdeInit = (PDDEINIT) mp2;
  135.  
  136.             if (((HWND) mp1 != dde->window->GetHandle()) && !strcmp((char *) pDdeInit->pszAppName, (char*) dde->app) && !strcmp((char *) pDdeInit->pszTopic, (char*) dde->topic))
  137.             {
  138.                 SHORT i;
  139.  
  140.                 for (i = 0; i < dde->clients; i++)
  141.                     if (dde->clientList[i] == (HWND) mp1)
  142.                         return FALSE;
  143.                 dde->clients += 1;
  144.                 dde->clientList = (ULONG *) realloc(dde->clientList, dde->clients * 4);
  145.                 dde->clientList[dde->clients - 1] = (HWND) mp1;
  146.                 dde->connected = TRUE;
  147.                 WinDdeRespond((HWND) mp1, dde->window->GetHandle(), (PSZ) dde->app, (PSZ) dde->topic, &ConvContext);
  148.                 dde->Connected((HWND) mp1);
  149.                 return TRUE;
  150.             }
  151.         }
  152.         break;
  153.     case WM_DDE_INITIATEACK:
  154.         {
  155.             PDDEINIT pDdeInit = (PDDEINIT) mp2;
  156.  
  157.             if (((HWND) mp1 != dde->window->GetHandle()) && (!dde->connected))
  158.             {
  159.                 if (dde->InitPossible((char *) pDdeInit->pszAppName, (char *) pDdeInit->pszTopic) == TRUE)
  160.                 {
  161.                     dde->server = (HWND) mp1;
  162.                     dde->connected = TRUE;
  163.                     dde->Connected((HWND) mp1);
  164.                     DosFreeMem(mp2);
  165.                 }
  166.                 else
  167.                     WinDdePostMsg((HWND) mp1, dde->window->GetHandle(), WM_DDE_TERMINATE, NULL, FALSE);
  168.                 return TRUE;
  169.             }
  170.         }
  171.         break;
  172.     case WM_DDE_REQUEST:
  173.         {
  174.             HWND client = (HWND) mp1;
  175.             PDDESTRUCT pDdeStruct = (PDDESTRUCT) mp2;
  176.  
  177.             dde->DataRequested((char *) DDES_PSZITEMNAME(pDdeStruct), pDdeStruct->usFormat, client);
  178.         }
  179.         break;
  180.     case WM_DDE_ADVISE:
  181.         {
  182.             HWND client = (HWND) mp1;
  183.             PDDESTRUCT pDdeStruct = (PDDESTRUCT) mp2;
  184.  
  185.             dde->AdviseRequested((char *) DDES_PSZITEMNAME(pDdeStruct), pDdeStruct->usFormat, client);
  186.         }
  187.         break;
  188.     case WM_DDE_UNADVISE:
  189.         {
  190.             HWND client = (HWND) mp1;
  191.  
  192.             dde->UnAdviseRequested(client);
  193.         }
  194.         break;
  195.     case WM_DDE_DATA:
  196.         {
  197.             PDDESTRUCT pDdeStruct = (PDDESTRUCT) mp2;
  198.  
  199.             if (dde->server != (HWND) mp1)
  200.                 return FALSE;
  201.             DosGetSharedMem(pDdeStruct, PAG_READ | PAG_WRITE);
  202.             dde->DataReceived(pDdeStruct->cbData, DDES_PABDATA(pDdeStruct), (char *) DDES_PSZITEMNAME(pDdeStruct), pDdeStruct->usFormat);
  203.         }
  204.         break;
  205.     case WM_DDE_ACK:
  206.         {
  207.             PDDESTRUCT pDdeStruct = (PDDESTRUCT) mp2;
  208.  
  209.             if (dde->server != (HWND) mp1)
  210.                 return FALSE;
  211.             if (pDdeStruct)
  212.             {
  213.                 dde->ack = pDdeStruct->fsStatus;
  214.                 DosFreeMem(pDdeStruct);
  215.             }
  216.             dde->Acknowledgement(dde->ack);
  217.             return TRUE;
  218.         }
  219.         break;
  220.     case WM_DDE_TERMINATE:
  221.         {
  222.             if (dde->connected)
  223.             {
  224.                 WinDdePostMsg(dde->server, dde->window->GetHandle(), WM_DDE_TERMINATE, NULL, FALSE);
  225.                 if (dde->isServer)
  226.                 {
  227.                     BOOL connect = FALSE;
  228.                     int i;
  229.  
  230.                     for (i = 0; i < dde->clients; i++)
  231.                     {
  232.                         if (dde->clientList[i] == (HWND) mp1)
  233.                             dde->clientList[i] = 0;
  234.                         if (dde->clientList[i] != 0)
  235.                             connect = TRUE;
  236.                     }
  237.                     dde->connected = connect;
  238.                     if (connect == FALSE)
  239.                         dde->DisConnected();
  240.                 }
  241.                 else
  242.                 {
  243.                     dde->connected = FALSE;
  244.                     dde->DisConnected();
  245.                 }
  246.             }
  247.         }
  248.         break;
  249.     }
  250.     return FALSE;
  251. }
  252.  
  253.  
  254. /*@ XDDE::Advise(const char *itemName, const SHORT format)
  255. @group data exchange
  256. @remarks Calls the server to establish a continous data-exchange
  257. @parameters char * itemName      the name of the requested item<BR>
  258.             SHORT format         needed format of data
  259. */
  260. BOOL XDDE::Advise(const char *itemName, const SHORT format)
  261. {
  262.     PDDESTRUCT pDdeStruct;
  263.  
  264.     if (!connected)
  265.         return FALSE;
  266.  
  267.     pDdeStruct = MakeDDEMsg(format, itemName, NULL, 0);
  268.     pDdeStruct->fsStatus |= DDE_FACKREQ;
  269.     return WinDdePostMsg(server, window->GetHandle(), WM_DDE_ADVISE, pDdeStruct, TRUE);
  270. }
  271.  
  272.  
  273. /*@ XDDE::UnAdvise(const char *itemName)
  274. @group data exchange
  275. @remarks Calls the server to stop continous data-exchange
  276. @parameters char * itemName      the name of the requested item
  277. @returns BOOL success
  278. */
  279. BOOL XDDE::UnAdvise(const char *itemName)
  280. {
  281.     PDDESTRUCT pDdeStruct;
  282.  
  283.     if (!connected)
  284.         return FALSE;
  285.  
  286.     pDdeStruct = MakeDDEMsg(0, itemName, NULL, 0);    // DDEFMT_TEXT
  287.     return WinDdePostMsg(server, window->GetHandle(), WM_DDE_UNADVISE, pDdeStruct, TRUE);
  288. }
  289.  
  290.  
  291. /*@ XDDE::GetData(const char *itemName, const SHORT format)
  292. @group data exchange
  293. @remarks Calls the server send data one time
  294. @parameters char * itemName      the name of the requested item<BR>
  295.             SHORT format         needed format of data
  296. */
  297. BOOL XDDE::GetData(const char *itemName, const SHORT format)
  298. {
  299.     PDDESTRUCT pDdeStruct;
  300.  
  301.     if (!connected)
  302.         return FALSE;
  303.  
  304.     pDdeStruct = MakeDDEMsg(format, itemName, NULL, 0);    // DDEFMT_TEXT
  305.     return WinDdePostMsg(server, window->GetHandle(), WM_DDE_REQUEST, pDdeStruct, TRUE);
  306. }
  307.  
  308.  
  309. /*@ XDDE::SendCommand(const char *itemName, const char *theCommand)
  310. @group data exchange
  311. @remarks Send a command
  312. @parameters char * itemName      the name of the requested item<BR>
  313.             char * command       command to execute
  314. */
  315. BOOL XDDE::SendCommand(const char *itemName, const char *theCommand)
  316. {
  317.     char command[200];
  318.     PDDESTRUCT pDdeStruct;
  319.  
  320.     if (!connected)
  321.         return FALSE;
  322.  
  323.     memcpy((char *) command, theCommand, strlen(theCommand) + 1);
  324.     pDdeStruct = MakeDDEMsg(DDEFMT_TEXT, itemName, &command, sizeof(command));
  325.     return WinDdePostMsg(server, window->GetHandle(), WM_DDE_EXECUTE, pDdeStruct, TRUE);
  326. }
  327.  
  328.  
  329. /*@ XDDE::PokeData(const OOL_WINDOWHANDLE handle, const char *itemName, const void *data, const ULONG s, const SHORT format)
  330. @group data exchange
  331. @remarks Poke data
  332. @parameters <t '°' c=2>
  333.                 °OOL_WINDOWHANDLE     °handle of the receiver
  334.             °char * itemName      °the name of the requested item
  335.             °void * data          °buffer which holds data
  336.             °ULONG size           °size of the buffer
  337.             °SHORT format         °format of the data (default is DDEF_TEXT)
  338.                 </t>
  339. */
  340. BOOL XDDE::PokeData(const OOL_WINDOWHANDLE handle, const char *itemName, const void *data, const ULONG s, const SHORT format)
  341. {
  342.     PDDESTRUCT pDdeStruct;
  343.     ULONG size = s;
  344.  
  345.     if (!connected)
  346.         return FALSE;
  347.  
  348.     if (size == 0)
  349.     {
  350.         if (format == DDEFMT_TEXT)
  351.             size = strlen((char *) data) + 1;
  352.         else
  353.             return FALSE;
  354.     }
  355.     pDdeStruct = MakeDDEMsg(format, itemName, data, size);    // DDEFMT_TEXT
  356.     return WinDdePostMsg(handle, window->GetHandle(), WM_DDE_POKE, pDdeStruct, TRUE);
  357. }
  358.  
  359.  
  360. /*@ XDDE::SendData(const OOL_WINDOWHANDLE client, const char *itemName, const void *data, const ULONG s, const SHORT format)
  361. @group data exchange
  362. @remarks Send data to a client
  363. @parameters <t '°' c=2>
  364.                 °OOL_WINDOWHANDLE     °handle of the receiver
  365.             °char * itemName      °the name of the requested item
  366.             °void * data          °buffer which holds data
  367.             °ULONG size           °size of the buffer
  368.             °SHORT format         °format of the data (default is DDEF_TEXT)
  369.                 </t>
  370. */
  371. BOOL XDDE::SendData(const OOL_WINDOWHANDLE client, const char *itemName, const void *data, const ULONG s, const SHORT format)
  372. {
  373.     PDDESTRUCT pDdeStruct;
  374.     ULONG size = s;
  375.  
  376.     if (!connected)
  377.         return FALSE;
  378.  
  379.     if (size == 0)
  380.     {
  381.         if (format == DDEFMT_TEXT)
  382.             size = strlen((char *) data) + 1;
  383.         else
  384.             return FALSE;
  385.     }
  386.     pDdeStruct = MakeDDEMsg(format, itemName, data, size);    // DDEFMT_TEXT
  387.  
  388.     PID pid;
  389.     TID tid;
  390.  
  391.     WinQueryWindowProcess(client, &pid, &tid);
  392.     DosGiveSharedMem(&pDdeStruct, pid, PAG_READ | PAG_WRITE);
  393.     return WinDdePostMsg(client, window->GetHandle(), WM_DDE_DATA, pDdeStruct, TRUE);
  394. }
  395.  
  396.  
  397. PDDESTRUCT XDDE::MakeDDEMsg(const USHORT usFormat, const char *itemName, const void *Data, const USHORT usDataSize)
  398. {
  399.     PDDESTRUCT pdde = (PDDESTRUCT) 0;
  400.     ULONG rc = 0;
  401.     ULONG usSegSize;
  402.     ULONG totalsize;
  403.  
  404.     usSegSize = strlen(itemName) + 1;
  405.     totalsize = sizeof(DDESTRUCT) + usDataSize + usSegSize;
  406.  
  407.     rc = DosAllocSharedMem((PPVOID) & pdde, (PSZ) 0, totalsize,
  408.                            PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_TILE
  409.                            | OBJ_GIVEABLE | OBJ_GETTABLE);
  410.  
  411.     if (rc)
  412.         return ((PDDESTRUCT) 0);
  413.  
  414.     memset((PVOID) pdde, 0, (size_t) usSegSize);
  415.     pdde->usFormat = usFormat;
  416.     pdde->offszItemName = (USHORT) sizeof(DDESTRUCT);
  417.     memcpy(DDES_PSZITEMNAME(pdde), itemName, usSegSize);
  418.     pdde->offabData = (USHORT) sizeof(DDESTRUCT) + usSegSize;
  419.     memcpy(DDES_PABDATA(pdde), Data, usDataSize);
  420.     pdde->fsStatus = 0;
  421.     pdde->cbData = (ULONG) totalsize;
  422.     return pdde;
  423. }
  424.  
  425.  
  426. /////////////////docs only
  427. /*@ XDDE::AdviseRequested()
  428. @group application notification
  429. @remarks Informs a server that an advise is requested. Override this
  430. function if you need this information.
  431. @parameters <t '°' c=2>
  432.                 °char * itemName      °the name of the requested item
  433.             °SHORT format         °format of the data
  434.             °OOL_WINDOWHANDLE     °handle of the client
  435.                 </t>
  436. */
  437.  
  438.  
  439. /*@ XDDE::Connected()
  440. @group application notification
  441. @remarks Informs a server that a client has been connected. Override this
  442. function if you need this information.
  443. @parameters OOL_WINDOWHANDLE     handle of the client
  444. */
  445.  
  446.  
  447. /*@ XDDE::DataReceived()
  448. @group application notification
  449. @remarks Informs that datas has been received. Override this
  450. function if you need this information.
  451. @parameters <t '°' c=2>
  452.                 °ULONG size        °size of the data
  453.             °void * data       °buffer which holds the data
  454.             °char * itemName   °item name
  455.             °SHORT format      °format of the data
  456.                 </t>
  457. */
  458.  
  459. /*@ XDDE::DataRequested()
  460. @group application notification
  461. @remarks Informs a server that datas are needed. Override this
  462. function if you need this information.
  463. @parameters <t '°' c=2>
  464.                 °char * itemName   °item name
  465.             °SHORT format      °format of the data
  466.             °OOL_WINDOWHANDLE  °the clients handle
  467.                 </t>
  468. */
  469.  
  470. /*@ XDDE::DisConnected()
  471. @group application notification
  472. @remarks Informs that the xdde-instance has no more connections. Override this
  473. function if you need this information.
  474. */
  475.  
  476.  
  477. /*@ XDDE::QueryOwner()
  478. @group misc
  479. @remarks Returns a pointer to the owner window
  480. @returns  XWindow *  the owner
  481. */
  482.  
  483.  
  484. /*@ XDDE::IsConnected()
  485. @group misc
  486. @remarks Returns if a connection is established or not
  487. @returns  BOOL connected
  488. */
  489.  
  490.  
  491. /*@ XDDE::InitPossible(char*, char*)
  492. @group connect
  493. @remarks Informs the application that a server is ready for a DDE connect. Return TRUE for a connect, otherwise return FALSE.
  494. On default this function returns allways TRUE, you must override this function to code the behaviour you want.
  495. @parameters char * appName     applivcation name of the possible server<BR>
  496.            char * toppicname  toppic-name that the possible server supports
  497. @returns  BOOL connect
  498. */
  499.