home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / CENVIW9.ZIP / DDECLI.LIB < prev    next >
Text File  |  1994-03-08  |  18KB  |  448 lines

  1. // DDEcli.lib - Library for common Client portion of DDE functions.
  2. // ver.1
  3. //
  4. //***** struct ddeSession: Structure to define a session
  5. // Many of the following functions refer to the parameters of a dde
  6. // session in some or all elements of a ddeSession structure, which
  7. // contains the following members (along with other non-documented
  8. // members that should be of no concern):
  9. //  .Application: string - DDE Server application name
  10. //  .Topic: string - DDE Server string
  11. //  .hwndClient: int - Window handle of the DDE client
  12. //  .hwndServer: int - Window handle of the DDE server
  13. //  .TerminateFunction: string - function to call when other party terminates
  14. //
  15. //
  16. //***** ServerDirectory(): Get the handle for this window
  17. // SYNTAX: int ServerDirectory(string Application,string Topic,struct[] ServerList)
  18. // WHERE: Application: DDE Server application string, or NULL for ALL
  19. //        Topic: DDE Server Topic, or NULL for ALL
  20. //        ServerList: array created for each entry.  Array elements are:
  21. //            .Application - Returned application name
  22. //            .Topic - Returned Topic name
  23. // RETURN: Count of elements in ServerList
  24. // MODIFY: Modifies ServerList to be an array.  Undefined if returns 0.
  25. //
  26. //
  27. //**** ConnectToServer(): Initialize (as client) session with server
  28. // SYNTAX: bool ConnectToServer(struct ddeSession)
  29. // WHERE: ddeSession with these parameters:
  30. //    .Application: DDE Server application string, or NULL for ALL
  31. //    .Topic: DDE Server Topic, or NULL for ALL
  32. // RETURN: Returns True if server found, else False
  33. // MODIFY: Sets the following fields if successful
  34. //    .Application: DDE Server application string returned by Server
  35. //    .Topic: DDE Server Topic returned by server
  36. //    .hwndClient: unique window handle
  37. //    .hwndServer: (probably) unique window handle
  38. //
  39. //
  40. //**** DisconnectFromServer(): Terminate client connection with server
  41. // SYNTAX: void DisconnectFromServer(struct ddeSession)
  42. //
  43. //
  44. // NOTE: If more than one server responds to the posting for Application:Topic,
  45. //       only the first connection will be maintained.
  46. //        TerminateFunction: Name of a function to call if the server should
  47. //               terminate this connection without us asking it to. If NULL
  48. //               then function not called. Called like this:
  49. //                   TerminateFunction(ddeSession)
  50. // RETURN: Return ServerHandle, which is the handle of the server connected
  51. //         to.  This ServerHandle
  52. //
  53. //
  54. //**** RequestDataFromServer()
  55. // SYNTAX: string RequestDataFromServer(struct ddeSession,string Item[,int Timeout])
  56. //
  57. // RETURN: NULL if no data for this item or if connection failed, else ascii
  58. //         string is the data for this item
  59. //
  60. //
  61. //**** DataLinkToServer()
  62. // SYNTAX: bool DataLinkToServer(struct ddeSession,string Item,
  63. //                               string NewDataFunction,bool SendData[,var OtherVar[,int Timeout]])
  64. // WHERE: NewDataFunction is of the form:
  65. //          void NewDataFunction(ddeSession,string Item,string Data,var OtherVar)
  66. //
  67. // NOTE: In the format without NewDataFunction, then server data is retrieved
  68. //       with DataLinkGetNext()
  69. //
  70. //**** DefDataLinkToServer()
  71. // SYNTAX: bool DefDataLinkToServer(struct ddeSession,string Item[,var OtherVar[,int Timeout]])
  72. //
  73. //
  74. //**** DefDataLinkGet()
  75. // SYNTAX: string DefDataLinkGet(struct ddeSession,string Item[,bool WaitForData[,var OtherVar]])
  76. // WHERE: Item: string to get data for.  If NULL then get any Item.  If !defined then
  77. //              retrieve any item AND set Item to the string retrieved
  78. //        WaitForData: True to wait until data arrives, else return immediately whether
  79. //                     data available or not.  Default TRUE
  80. //        OtherVar: Same var passed in DefDataLinkToServer()
  81. //
  82. //
  83. //**** DataUnlink(ddeSession[,Item[,int Timeout]])
  84. //
  85. // Item is NULL to terminate ALL hotlinks
  86. //
  87. //
  88. //**** DdeExecute()
  89. // SYNTAX: bool DdeExecute(struct ddeSession,string Commands[,int Timeout])
  90. //
  91.  
  92. #include <DDE.lib>
  93.  
  94. #define WM_NCDESTROY        0x0082
  95.  
  96. DDELibClientFunction(hwnd,msg,wParm,lParm,pddeSession)
  97. {
  98.    if ( WM_DESTROY == msg ) {
  99.       // if there is still a connection, then end links and post terminate message
  100.       if ( defined(pddeSession.hwndServer) ) {
  101.          DataUnlink(pddeSession);
  102.          PostMessage(pddeSession.hwndServer,WM_DDE_TERMINATE,hwnd,0);
  103.       }
  104.       undefine(pddeSession.hwndServer);
  105.       undefine(pddeSession.HotLink);
  106.       return;
  107.    }
  108.  
  109.    // skip any messages that aren't for this session from our server while
  110.    // we're waiting for a message (except for WM_DDE_INITIATE)
  111.    if ( !defined(pddeSession.hwndServer)  ||  wParm != pddeSession.hwndServer ) {
  112.       if ( WM_DDE_INITIATE != pddeSession.PostedMessage )
  113.          return;
  114.    }
  115.  
  116.    switch ( msg ) {
  117.       case WM_DDE_ACK:
  118.          if ( WM_DDE_INITIATE == pddeSession.PostedMessage ) {
  119.             if ( defined(pddeSession.hwndServer) ) {
  120.                // already found a serer, so terminate this new connection
  121.                PostMessage(wParm,WM_DDE_TERMINATE,hwnd,0);
  122.             } else {
  123.                // We have a connection!
  124.                ClientWmDdeAckInitiate(pddeSession,wParm,LoWord(lParm),HiWord(lParm));
  125.             }
  126.             return(0);
  127.          } else {
  128.             lDdeAck = WordToDdeAck(LoWord(lParm));
  129.             switch ( pddeSession.PostedMessage ) {
  130.                case WM_DDE_UNADVISE:
  131.                   // unadvise message was accepted
  132.                case WM_DDE_REQUEST:
  133.                   // dang, data wasn't found
  134.                   pddeSession.ItemAtom = HiWord(lParm);
  135.                   pddeSession.PostedMessage = 0;
  136.                   return(0);
  137.                case WM_DDE_ADVISE:
  138.                   // check that it's the same name we're looking for
  139.                   if ( !stricmp(GetAtomString(HiWord(lParm)),pddeSession.Item) ) {
  140.                      // this is the message response to our advise link request
  141.                      pddeSession.PostedMessage = 0;
  142.                      pddeSession.MakeLinkSuccess = lDdeAck.fAck;
  143.                      return(0);
  144.                   }
  145.                   break;
  146.                case WM_DDE_EXECUTE:
  147.                   if ( HiWord(lParm) == pddeSession.hCommand ) {
  148.                      pddeSession.ExecuteSuccess = lDdeAck.fAck;
  149.                      pddeSession.PostedMessage = 0;
  150.                      return(0);
  151.                   }
  152.                   break;
  153.             }
  154.          }
  155.          break;
  156.  
  157.       case WM_DDE_DATA:
  158.          ClientWmDdeData(pddeSession,LoWord(lParm),HiWord(lParm));
  159.          return 0;
  160.  
  161.       case WM_DDE_TERMINATE:
  162.          PostMessage(wParm,WM_DDE_TERMINATE,hwnd,0);
  163.          if ( defined(pddeSession.TerminateFunction) ) {
  164.             function(pddeSession.TerminateFunction,pddeSession);
  165.             DataUnlink(pddeSession);
  166.          }
  167.          undefine(pddeSession.hwndServer);
  168.          undefine(pddeSession.HotLink);
  169.          pddeSession.PostedMessage = 0;
  170.          return 0;
  171.    }
  172. }
  173.  
  174. ClientWmDdeData(pddeSession,hDdeData,aItem)
  175. {
  176.    // Get ascii name of the data item
  177.    lItem = GetAtomString(aItem);
  178.  
  179.    if ( hDdeData )
  180.       lDdeData = DdeDataHandleToStructure(hDdeData);
  181.  
  182.    // Initialize DDeAck structure
  183.    lDdeAck.bAppReturnedCode = 0;
  184.    lDdeAck.fBusy = FALSE;
  185.    lDdeAck.fAck = FALSE;
  186.  
  187.    // Is this in response to WM_DDE_REQUEST, or is it a link
  188.    lRequested = WM_DDE_REQUEST == pddeSession.PostedMessage
  189.              && !stricmp(lItem,pddeSession.Item)
  190.              && hDdeData && CF_TEXT == lDdeData.cfFormat;
  191.    if ( lRequested ) {
  192.       pddeSession.PostedMessage = 0;
  193.       pddeSession.Data = lDdeData.Value;
  194.       lDdeAck.fAck = TRUE ;
  195.       // Save atom to be deleted when done
  196.       pddeSession.ItemAtom = aItem;
  197.    } else {
  198.       // check if we are in link mode, and so may be looking for warm or hot link
  199.       if ( defined(ddeSession.HotLink)
  200.         && ( !hDdeData || CF_TEXT == lDdeData.cfFormat ) ) {
  201.          for ( lIndex = GetArraySpan(ddeSession.HotLink); 0 <= lIndex; lIndex-- ) {
  202.             if ( !stricmp(ddeSession.HotLink[lIndex].Item,lItem) ) {
  203.                lHotLink = ddeSession.HotLink[lIndex];
  204.                lDdeAck.fAck = TRUE;
  205.                break;
  206.             }
  207.          }
  208.       }
  209.    }
  210.  
  211.    // Acknowledge if necessary
  212.    if ( lDdeData.fAckReq ) {
  213.       wStatus = DdeAckToWord(lDdeAck);
  214.       if ( !PostMessage(wParam,WM_DDE_ACK,pddeSession.hwndClient,wStatus,aItem) ) {
  215.          GlobalFree (hDdeData) ;
  216.          if ( !lRequested ) GlobalDeleteAtom(aItem);
  217.          return;
  218.       }
  219.    } else
  220.       if ( !lRequested ) GlobalDeleteAtom(aItem);
  221.  
  222.    // Clean up
  223.    if ( lDdeData.fRelease  ||  !lDdeAck.fAck )
  224.       GlobalFree (hDdeData) ;
  225.  
  226.    if ( defined(lHotLink) ) {
  227.       function( lHotLink.NewDataFunction,pddeSession, lHotLink.Item,
  228.                 hDdeData ? lDdeData.Value : NULL, lHotLink.OtherVar );
  229.    }
  230. }
  231.  
  232. ClientWmDdeAckInitiate(pddeSession,pServerHandle,pAtomApp,pAtomTopic)
  233. {
  234.    pddeSession.hwndServer = pServerHandle;
  235.    pddeSession.Application = GetAtomString(pAtomApp);
  236.    pddeSession.Topic = GetAtomString(pAtomTopic);
  237. }
  238.  
  239. ConnectToServer(pddeSession)
  240. {
  241.    undefine(pddeSession.hwndServer);
  242.    pddeSession.PostedMessage = 0;
  243.    pddeSession.hwndClient = MakeWindow(DDELibMainHwnd,NULL,"DDELibClientFunction",
  244.                                        NULL,WS_CHILD,0,0,0,0,NULL,pddeSession);
  245.    if ( pddeSession.hwndClient ) {
  246.  
  247.       // try to connect to server
  248.       csAtomApp = pddeSession.Application ? GlobalAddAtom(pddeSession.Application) : 0 ;
  249.       csAtomTop = pddeSession.Topic ? GlobalAddAtom(pddeSession.Topic) : 0 ;
  250.  
  251.       // Send message to all windows to initiate DDE connection
  252.       Multitask(False);
  253.       pddeSession.PostedMessage = WM_DDE_INITIATE;
  254.       SendMessage(0xFFFF,WM_DDE_INITIATE,pddeSession.hwndClient,csAtomApp,csAtomTop);
  255.       pddeSession.PostedMessage = 0;
  256.       MultiTask(True);
  257.  
  258.       // undo atoms that were made
  259.       if ( csAtomApp ) GlobalDeleteAtom(csAtomApp);
  260.       if ( csAtomTop ) GlobalDeleteAtom(csAtomTop);
  261.  
  262.       if ( !defined(pddeSession.hwndServer) ) {
  263.          // connection didn't work, and so remove the window
  264.          BreakWindow(pddeSession.hwndClient);
  265.       }
  266.    }
  267.    return( defined(pddeSession.hwndServer) );
  268. }
  269.  
  270. DisconnectFromServer(pddeSession)
  271. {
  272.    // client session. Simply close the client window
  273.    BreakWindow(pddeSession.hwndClient);
  274. }
  275.  
  276. RequestDataFromServer(pddeSession,pItem,pTimeout)
  277. {
  278.    pddeSession.ItemAtom = GlobalAddAtom(pItem);
  279.    pddeSession.Item = pItem;
  280.    pddeSession.Data = NULL;
  281.    Multitask(False);
  282.    if ( defined(pddeSession.hwndServer)
  283.      && PostMessage(pddeSession.hwndServer,pddeSession.PostedMessage = WM_DDE_REQUEST,
  284.                     pddeSession.hwndClient,CF_TEXT,pddeSession.ItemAtom) )
  285.       DoPostedDDEMessage(pddeSession,2 < va_arg() ? pTimeout : DEFAULT_TIMEOUT );
  286.    pddeSession.PostedMessage = 0;
  287.    Multitask(True);
  288.    GlobalDeleteAtom(pddeSession.ItemAtom);
  289.    undefine( pddeSession.Item );
  290.    return(pddeSession.Data);
  291. }
  292.  
  293. DataLinkToServer(pddeSession,pItem,pNewDataFunction,pSendData,pOtherVar,pTimeout)
  294. {
  295.    bool lSuccess = False;  // assume failure
  296.    pddeSession.ItemAtom = GlobalAddAtom(pItem);
  297.    pddeSession.Item = pItem;
  298.    lDdeAdvise.fAckReq   = TRUE ;
  299.    lDdeAdvise.fDeferUpd = pSendData ? FALSE : TRUE ;
  300.    lDdeAdvise.cfFormat  = CF_TEXT ;
  301.    hDdeAdvise = DdeAdviseStuctureToHandle(lDdeAdvise);
  302.    Multitask(False);
  303.    if ( defined(pddeSession.hwndServer) ) {
  304.       // This link will be added to the end of the HotLink array
  305.       pddeSession.MakeLinkSuccess = False; // assume failure
  306.       if ( PostMessage(pddeSession.hwndServer,pddeSession.PostedMessage = WM_DDE_ADVISE,
  307.                        pddeSession.hwndClient,hDdeAdvise,pddeSession.ItemAtom) )
  308.          DoPostedDDEMessage(pddeSession,5 < va_arg() ? pTimeout : DEFAULT_TIMEOUT );
  309.       pddeSession.PostedMessage = 0;
  310.       if ( pddeSession.MakeLinkSuccess ) {
  311.          lSuccess = True;
  312.          lLinkIndex = defined(ddeSession.HotLink) ? 1 + GetArraySpan(ddeSession.HotLink): 0 ;
  313.          strcpy( ddeSession.HotLink[lLinkIndex].Item, pItem );
  314.          strcpy( ddeSession.HotLink[lLinkIndex].NewDataFunction, pNewDataFunction );
  315.          ddeSession.HotLink[lLinkIndex].OtherVar = pOtherVar;
  316.       }
  317.       undefine(pddeSession.MakeLinkSuccess);
  318.    }
  319.    Multitask(True);
  320.    if ( !lSuccess )
  321.       GlobalFree(hDdeAdvise);
  322.    GlobalDeleteAtom(pddeSession.ItemAtom);
  323.    undefine( pddeSession.Item );
  324.    return(lSuccess);
  325. }
  326.  
  327. DefDataLinkToServer(pddeSession,pItem,pOtherVar,pTimeout)
  328. {
  329.    switch( va_arg() ) {
  330.       case 2: return DataLinkToServer(pddeSession,pItem,"DefaultNewDataFunction",TRUE,0);
  331.       case 3: return DataLinkToServer(pddeSession,pItem,"DefaultNewDataFunction",TRUE,pOtherVar);
  332.       case 4: return DataLinkToServer(pddeSession,pItem,"DefaultNewDataFunction",TRUE,pOtherVar,pTimeout);
  333.  
  334.    }
  335.    abort(); // should'nt get here
  336. }
  337.  
  338. DataUnlink(pddeSession,pItem,pTimeout)
  339. {
  340.    // find this link in current array
  341.    if ( defined(pddeSession.HotLink) ) {
  342.       lItem = ( 1 == va_arg() ) ? NULL : pItem ;
  343.       MultiTask(False);
  344.       if ( !lItem ) {
  345.          undefine(pddeSession.HotLink);
  346.          undefine(pddeSession.DefaultReceiveList);
  347.       } else {
  348.          lArraySpan = GetArraySpan(pddeSession.HotLink);
  349.          for ( lIndex = lArraySpan; 0 <= lIndex; lIndex-- ) {
  350.             if ( !stricmp(lItem,pddeSession.HotLink[lIndex].Item) ) {
  351.                if ( !strcmp(pddeSession.HotLink[lIndex].NewDataFunction,"DefaultNewDataFunction") ) {
  352.                   // this is a default data function; remove waiting instances
  353.                   while ( DefDataLinkGet(pddeSession,lItem,False) ) ;
  354.                }
  355.                // remove this element from array, and shrink the rest down
  356.                if ( 0 == lArraySpan )
  357.                   undefine(pddeSession.HotLink);
  358.                else {
  359.                   while ( lIndex++ < lArraySpan )
  360.                      pddeSession.HotLink[lIndex-1] = pddeSession.HotLink[lIndex];
  361.                   SetArraySpan(pddeSession.HotLink,lArraySpan-1);
  362.                }
  363.                break;
  364.             }
  365.          }
  366.       }
  367.  
  368.       if ( !lItem  ||  0 <= lIndex ) {
  369.          // send server message to stop advising about this item
  370.          pddeSession.ItemAtom = lItem ? GlobalAddAtom(lItem) : 0;
  371.          pddeSession.Item = lItem;
  372.          if ( defined(pddeSession.hwndServer) ) {
  373.             if ( PostMessage(pddeSession.hwndServer,pddeSession.PostedMessage = WM_DDE_UNADVISE,
  374.                              pddeSession.hwndClient,CF_TEXT,pddeSession.ItemAtom) )
  375.                DoPostedDDEMessage(pddeSession,2 < va_arg() ? pTimeout : DEFAULT_TIMEOUT );
  376.             pddeSession.PostedMessage = 0;
  377.          }
  378.          if ( pddeSession.ItemAtom )
  379.             GlobalDeleteAtom(pddeSession.ItemAtom);
  380.       }
  381.    }
  382.    Multitask(True);
  383. }
  384.  
  385. DefaultNewDataFunction(pddeSession,pItem,pData,pOtherVar)
  386. {  // add this new data to the end of maintained DefaultReceiveList
  387.    if ( pData ) {
  388.       // add this new data to the end of the list
  389.       lIndex = defined(pddeSession.DefaultReceiveList)
  390.              ? 1 + GetArraySpan(pddeSession.DefaultReceiveList) : 0 ;
  391.       strcpy(pddeSession.DefaultReceiveList[lIndex].Item,pItem);
  392.       strcpy(pddeSession.DefaultReceiveList[lIndex].Data,pData);
  393.       pddeSession.DefaultReceiveList[lIndex].OtherVar = pOtherVar;
  394.    }
  395. }
  396.  
  397. DefDataLinkGet(pddeSession,pItem,pWaitForData,pOtherVar)
  398. {
  399.    lData = NULL;  // assume failure
  400.    lWaitForData = 2 < va_arg() ? pWaitForData : TRUE ;
  401.    do {
  402.       // Find Item in our list of received data
  403.       MultiTask(False);
  404.       if ( defined(pddeSession.DefaultReceiveList) ) {
  405.          lReceiveCount = 1 + GetArraySpan(pddeSession.DefaultReceiveList);
  406.          for ( li = 0; li < lReceiveCount; li++ ) {
  407.             if ( !defined(pItem)  ||  !pItem
  408.               || !stricmp(pItem,pddeSession.DefaultReceiveList[li].Item) ) {
  409.                lData = pddeSession.DefaultReceiveList[li].Data;
  410.                if ( 3 < va_arg() ) pOtherVar = pddeSession.DefaultReceiveList[li].OtherVar;
  411.                if ( !defined(pItem) ) pItem = pddeSession.DefaultReceiveList[li].Item;
  412.                // remove this data from the DefaultReceiveList, and compact array
  413.                for ( lj = li + 1; lj < lReceiveCount; lj++ )
  414.                   pddeSession.DefaultReceiveList[lj-1] = pddeSession.DefaultReceiveList[lj];
  415.                if ( 0 == --lReceiveCount )
  416.                   undefine(pddeSession.DefaultReceiveList);
  417.                else
  418.                   SetArraySpan(pddeSession.DefaultReceiveList,lReceiveCount-1);
  419.                break;
  420.             }
  421.          }
  422.       }
  423.       MultiTask(True);
  424.    } while ( !lData && lWaitForData && defined(pddeSession.hwndServer) && DoWindows() );
  425.    return lData;
  426. }
  427.  
  428. DdeExecute(pddeSession,pCommands,pTimeout)
  429. {
  430.    lCommandLen = 1 + strlen(pCommands);
  431.    pddeSession.ExecuteSuccess = False; // assume failure
  432.    assert( pddeSession.hCommand = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,lCommandLen) );
  433.    poke(GlobalLock(pddeSession.hCommand),pCommands,lCommandLen);
  434.    GlobalUnlock(pddeSession.hCommand);
  435.    Multitask(False);
  436.    if ( defined(pddeSession.hwndServer) ) {
  437.       if ( PostMessage(pddeSession.hwndServer,pddeSession.PostedMessage = WM_DDE_EXECUTE,
  438.                        pddeSession.hwndClient,0,pddeSession.hCommand) )
  439.          DoPostedDDEMessage(pddeSession,2 < va_arg() ? pTimeout : DEFAULT_TIMEOUT );
  440.       pddeSession.PostedMessage = 0;
  441.    }
  442.    Multitask(True);
  443.    // if it worked then hCommand will have been set to 0
  444.    GlobalFree(pddeSession.hCommand);
  445.    return pddeSession.ExecuteSuccess;
  446. }
  447.  
  448.