home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c221 / 7.ddi / MWHC.007 / S7 < prev    next >
Encoding:
Text File  |  1991-09-05  |  16.2 KB  |  627 lines

  1. /****************************************************************************
  2.  
  3.     MODULE: SERVDATA.C
  4.  
  5.     PURPOSE: Maintains conversation information.
  6.  
  7.  
  8. ****************************************************************************/
  9.  
  10. #include "windows.h"
  11.  
  12. #include "dde.h"
  13. #include "server.h"
  14. #include <string.h>
  15.  
  16. struct CONV
  17. {
  18.     HWND hwndServerDDE;
  19.     HWND hwndClientDDE;
  20.     BOOL bInClientRequestedTerminate;
  21. };
  22.  
  23. struct ADVISE
  24. {
  25.     HWND    hwndServerDDE;
  26.     HWND    hwndClientDDE;
  27.     int         nItem;
  28.     ATOM        atomItem;
  29.     BOOL        bAckRequest;
  30.     BOOL        bDeferUpdate;
  31.     BOOL        bAwaitingAck;
  32.     HANDLE      hData;
  33. };
  34.  
  35. struct CONV Conv[CONV_MAX_COUNT];
  36. static int nConvCount = 0;
  37. static struct ADVISE Advise[ADVISE_MAX_COUNT];
  38. static int nAdviseCount = 0;
  39.  
  40. struct ADVISE * NEAR FindAdvise(HWND, int);
  41. struct CONV *    NEAR FindConv(HWND);
  42.  
  43.  
  44. /****************************************************************************
  45.  
  46.     FUNCTION: AddAdvise
  47.  
  48.     PURPOSE:  Register a new hot or warm link to a specified client, for
  49.           a specified server application item (1, 2, or 3).
  50.  
  51. ****************************************************************************/
  52. BOOL AddAdvise(hwndServerDDE, hDDEAdviseOptions, atomItem, nItem)
  53.     HWND   hwndServerDDE;
  54.     HANDLE hDDEAdviseOptions;
  55.     ATOM   atomItem;
  56.     int    nItem;
  57. {
  58.     struct ADVISE     * pAdvise;
  59.     DDEADVISE _Dfar     * lpDDEAdviseOptions;
  60.     int         nAdviseIndex;
  61.  
  62.     if (nAdviseCount >= ADVISE_MAX_COUNT)
  63.     {
  64.     MessageBox(hwndMain,
  65.             "Maximum advisories exceeded", 
  66.             "Server",
  67.             MB_ICONEXCLAMATION | MB_OK);
  68.         return (FALSE);
  69.     }
  70.     if ((lpDDEAdviseOptions 
  71.           = (DDEADVISE _Dfar *)GlobalLock(hDDEAdviseOptions)) == NULL)
  72.         return (FALSE);
  73.    
  74.     for (pAdvise = Advise, nAdviseIndex = 0;
  75.      nAdviseIndex < nAdviseCount;
  76.      pAdvise++, nAdviseIndex++)
  77.     {
  78.     if (pAdvise->hwndServerDDE == hwndServerDDE
  79.         && pAdvise->nItem == nItem)
  80.     {
  81.         MessageBox(hwndMain,
  82.         "Advisory (paste link) already established",
  83.         "Server",
  84.         MB_ICONEXCLAMATION | MB_OK);
  85.         GlobalUnlock(hDDEAdviseOptions);
  86.         return (FALSE);
  87.     }
  88.     }
  89.  
  90.     pAdvise = Advise + nAdviseCount++;
  91.  
  92.     pAdvise->hwndServerDDE = hwndServerDDE;
  93.     pAdvise->hwndClientDDE = GetHwndClientDDE(hwndServerDDE);
  94.     pAdvise->nItem = nItem;
  95.     pAdvise->atomItem = atomItem;
  96.     pAdvise->bAckRequest = lpDDEAdviseOptions->fAckReq;
  97.     pAdvise->bDeferUpdate = lpDDEAdviseOptions->fDeferUpd;
  98.     pAdvise->bAwaitingAck = FALSE;
  99.  
  100.     GlobalUnlock(hDDEAdviseOptions);
  101.     return (TRUE);
  102. }
  103.  
  104.  
  105.  
  106. /****************************************************************************
  107.  
  108.     FUNCTION: AddConv
  109.  
  110.     PURPOSE:  Register a new conversation with a client window
  111.  
  112. ****************************************************************************/
  113. BOOL AddConv(hwndServerDDE, hwndClientDDE)
  114.     HWND  hwndServerDDE;
  115.     HWND  hwndClientDDE;
  116. {
  117.     struct CONV * pConv;
  118.  
  119.     if (nConvCount >= CONV_MAX_COUNT)
  120.     {
  121.         return (FALSE);
  122.     }
  123.  
  124.     if (FindConv(hwndServerDDE) != NULL)
  125.     {
  126.     return (FALSE); /* conversation already added */
  127.     }
  128.  
  129.     pConv = Conv + nConvCount++;
  130.     pConv->hwndServerDDE = hwndServerDDE;
  131.     pConv->hwndClientDDE = hwndClientDDE;
  132.     pConv->bInClientRequestedTerminate = FALSE;
  133.     return (TRUE);
  134. }
  135.  
  136.  
  137.  
  138. /***********************************************************************
  139.  
  140.     FUNCTION:  AtLeastOneConvActive
  141.  
  142.     PURPOSE:   Used during termination of application, to
  143.            determine whether any conversations are still active
  144.            while the conversations are being terminated.
  145.  
  146. ***********************************************************************/
  147. BOOL AtLeastOneConvActive()
  148. {
  149.     return (nConvCount? TRUE: FALSE);
  150. }
  151.  
  152.  
  153.  
  154. /****************************************************************************
  155.  
  156.     FUNCTION: CheckOutSentData
  157.  
  158.     PURPOSE:  Set Awaiting Ack state to true for specified item.
  159.  
  160. ****************************************************************************/
  161. void CheckOutSentData(hwndServerDDE, nItem, atomItem, hData)
  162.     HWND    hwndServerDDE;
  163.     int     nItem;
  164.     ATOM    atomItem;
  165.     HANDLE  hData;
  166. {
  167.     struct ADVISE * pAdvise;
  168.  
  169.     if ((pAdvise = FindAdvise(hwndServerDDE, nItem)) == 0)
  170.         return;
  171.     pAdvise->bAwaitingAck = TRUE;
  172.     pAdvise->atomItem = atomItem;
  173.     pAdvise->hData = hData;
  174.     return;
  175. }
  176.  
  177.  
  178.  
  179. /****************************************************************************
  180.  
  181.     FUNCTION: DoEditCopy
  182.  
  183.     PURPOSE:  Copy selected data to clipboard in two formats:
  184.           CF_TEXT and (registered) "Link" format.
  185.  
  186. ****************************************************************************/
  187. void DoEditCopy(nItem)
  188.     int   nItem;
  189. {
  190.  
  191.     /* Format string and set clipboard data here */
  192.     HANDLE  hTextData;
  193.     HANDLE  hConvData;
  194.     char  szItemValue[ITEM_VALUE_MAX_SIZE+1];
  195.     LPSTR  lpTextData, lpConvData;
  196.  
  197.     if (!GetDlgItemText(hwndMain, nItem, szItemValue, ITEM_VALUE_MAX_SIZE))
  198.     strcpy(szItemValue, " ");
  199.  
  200.     /* Copy item value in CF_TEXT format to global memory object */
  201.  
  202.     if ((hTextData
  203.       = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, (DWORD)lstrlen(szItemValue)+1))==0)
  204.     return;
  205.     if ((lpTextData = GlobalLock(hTextData)) == NULL)
  206.     {
  207.     GlobalFree(hTextData);
  208.     return;
  209.     }
  210.     lstrcpy(lpTextData, szItemValue);
  211.     GlobalUnlock(hTextData);
  212.  
  213.     /* Copy item value in "Link" format to global memory object */
  214.  
  215.     if ((hConvData
  216.       = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
  217.         (DWORD)APP_MAX_SIZE+TOPIC_MAX_SIZE+ITEM_NAME_MAX_SIZE+4)) == 0)
  218.        return;
  219.     if ((lpConvData = GlobalLock(hConvData)) == NULL)
  220.     {
  221.        GlobalFree(hConvData);
  222.        return;
  223.     }
  224.  
  225.     /* Compose paste link string, each sub-string is null terminated */
  226.     /* Format is <app> <null> <topic> <null> <item> <null> <null>    */
  227.     lstrcpy(lpConvData, "Server");
  228.     lpConvData = lpConvData + lstrlen(lpConvData) + 1;    /* '+1' adds null */
  229.     lstrcpy(lpConvData, szDocName);   /* topic */
  230.     lpConvData += (lstrlen(lpConvData) + 1);
  231.     lstrcpy(lpConvData, "item#");
  232.     lpConvData[4] = '1' + nItem - 1;
  233.     *(lpConvData + lstrlen(lpConvData) + 1) = 0;  /* final null */
  234.  
  235.     GlobalUnlock(hConvData);
  236.  
  237.     if (OpenClipboard(hwndMain))
  238.     {
  239.        EmptyClipboard();
  240.  
  241.        SetClipboardData(CF_TEXT, hTextData);
  242.        SetClipboardData(cfLink, hConvData);
  243.  
  244.        CloseClipboard();
  245.     }
  246.     else
  247.     {
  248.        GlobalFree(hTextData);
  249.        GlobalFree(hConvData);
  250.     }
  251.    
  252.     return;
  253. }
  254.  
  255.  
  256.  
  257. /****************************************************************************
  258.  
  259.     FUNCTION: FindAdvise
  260.  
  261.     PURPOSE:  Find advisory data for a specific conversation item.
  262.  
  263. ****************************************************************************/
  264. struct ADVISE * NEAR FindAdvise(hwndServerDDE, nItem)
  265.     HWND hwndServerDDE;
  266.     int  nItem;
  267. {
  268.     struct ADVISE * pAdvise;
  269.     int             nAdviseIndex;
  270.  
  271.     for (nAdviseIndex = 0, pAdvise = Advise;
  272.          nAdviseIndex < nAdviseCount;
  273.          nAdviseIndex++, pAdvise++)
  274.     {
  275.     if (pAdvise->hwndServerDDE == hwndServerDDE
  276.             && pAdvise->nItem == nItem)
  277.         {
  278.             return (pAdvise);
  279.         }
  280.     }
  281.     return (NULL);
  282. }
  283.  
  284.  
  285.  
  286.  
  287.  
  288. /****************************************************************************
  289.  
  290.     FUNCTION: FindConv
  291.  
  292.     PURPOSE:  Find the conversation for a specified server DDE window.
  293.  
  294. ****************************************************************************/
  295. struct CONV * NEAR FindConv(hwndServerDDE)
  296.     HWND  hwndServerDDE;
  297. {
  298.     struct CONV * pConv;
  299.     int       nConvIndex;
  300.    
  301.     for (nConvIndex = 0, pConv = Conv;
  302.      nConvIndex < nConvCount;
  303.      nConvIndex++, pConv++)
  304.     {
  305.     if (pConv->hwndServerDDE == hwndServerDDE)
  306.         return (pConv);
  307.     }
  308.     return (NULL);
  309. }
  310.  
  311.  
  312.  
  313. /****************************************************************************
  314.  
  315.     FUNCTION: GetAdviseData
  316.  
  317.     PURPOSE:  Get advisory data for a specified conversation item.
  318.  
  319. ****************************************************************************/
  320. BOOL GetAdviseData(hwndServerDDE, nItem, szItemName, szItemValue,
  321.                    pbDeferUpdate, pbAckRequest)
  322.     HWND   hwndServerDDE;
  323.     int    nItem;
  324.     char * szItemName;
  325.     char * szItemValue;
  326.     BOOL * pbDeferUpdate;
  327.     BOOL * pbAckRequest;
  328. {
  329.     struct ADVISE * pAdvise;
  330.  
  331.     if ((pAdvise = FindAdvise(hwndServerDDE, nItem)) == NULL)
  332.         return (FALSE);
  333.     strcpy(szItemName, "Item#");
  334.     szItemName[4] = pAdvise->nItem==1? '1': pAdvise->nItem==2? '2': '3';
  335.     *pbDeferUpdate = pAdvise->bDeferUpdate;
  336.     *pbAckRequest = pAdvise->bAckRequest;
  337.     if (!GetDlgItemText(hwndMain, nItem, szItemValue, ITEM_VALUE_MAX_SIZE))
  338.         strcpy(szItemValue," ");
  339.  
  340.     return (TRUE);
  341. }
  342.  
  343.  
  344.  
  345. /****************************************************************************
  346.  
  347.     FUNCTION: GetHwndClientDDE
  348.  
  349.     PURPOSE:  Get the hwnd of the client in conversation with a specified
  350.           server DDE window.
  351.  
  352. ****************************************************************************/
  353. HWND GetHwndClientDDE(hwndServerDDE)
  354.     HWND  hwndServerDDE;
  355. {
  356.     struct CONV * pConv;
  357.  
  358.     if ((pConv = FindConv(hwndServerDDE)) == NULL)
  359.     return (NULL);
  360.     return (pConv->hwndClientDDE);
  361. }
  362.  
  363.  
  364.  
  365. /****************************************************************************
  366.  
  367.     FUNCTION: GetNextAdvise
  368.  
  369.     PURPOSE:  Find a client that needs to be notified that a value of
  370.           a specified item (a hot or warm link item) has changed.
  371.           Since a hot or warm link to the item may have been established
  372.           for multiple conversations (multiple clients), this function
  373.           is set up to step through the list of such conversations.
  374.           Start the list by passing a NULL hwndClientDDE.  To get the
  375.           next conversation in the list, pass the previous client returned
  376.           by this function.
  377.  
  378. ****************************************************************************/
  379. HWND GetNextAdvise(hwndServerDDE, nItem)
  380.     HWND hwndServerDDE;
  381.     int  nItem;
  382. {
  383.     struct ADVISE * pAdvise;
  384.     int             nAdviseIndex;
  385.  
  386.     if (hwndServerDDE)
  387.     {
  388.         for (nAdviseIndex = 0, pAdvise = Advise;
  389.              nAdviseIndex < nAdviseCount;
  390.              nAdviseIndex++, pAdvise++)
  391.         {
  392.         if (pAdvise->hwndServerDDE == hwndServerDDE
  393.                 && pAdvise->nItem == nItem)
  394.             {
  395.                 pAdvise++;
  396.                 break;
  397.             }
  398.         }
  399.         if (nAdviseIndex >= nAdviseCount)
  400.             return (NULL);
  401.     }
  402.     else
  403.     {
  404.         pAdvise = Advise;
  405.         nAdviseIndex = 0;
  406.     }
  407.     for ( ; nAdviseIndex < nAdviseCount; nAdviseIndex++, pAdvise++)
  408.     {
  409.         if (pAdvise->nItem == nItem)
  410.         {
  411.         return (pAdvise->hwndServerDDE);
  412.         }
  413.     }
  414.     return (NULL);
  415. }
  416.  
  417.  
  418.  
  419. /****************************************************************************
  420.  
  421.     FUNCTION: GetNextConv
  422.  
  423.     PURPOSE:  Get next client in list of conversations.  To get the
  424.           first hwndServerDDE in the conversation list, pass in a NULL
  425.           value for hwndServerDDE.
  426.  
  427. ****************************************************************************/
  428. HWND GetNextConv(hwndServerDDE)
  429.     HWND hwndServerDDE;
  430. {
  431.     struct CONV * pConv;
  432.     int       nConvIndex;
  433.  
  434.     if (hwndServerDDE)
  435.     {
  436.     for (nConvIndex = 0, pConv = Conv;
  437.          nConvIndex < nConvCount;
  438.          nConvIndex++, pConv++)
  439.         {
  440.         if (pConv->hwndServerDDE == hwndServerDDE)
  441.             {
  442.         if (++nConvIndex < nConvCount)
  443.             return (++pConv)->hwndServerDDE;
  444.                 else
  445.                     return (NULL);
  446.             }
  447.         }
  448.         return (NULL);
  449.     }
  450.     if (nConvCount > 0)
  451.     return (Conv[0].hwndServerDDE);
  452.     else
  453.         return (NULL);
  454. }
  455.  
  456.  
  457.  
  458. /****************************************************************************
  459.  
  460.     FUNCTION: GlobalFreeSentData
  461.  
  462.     PURPOSE:  A global memory object (hData) was sent in a WM_DDE_DATA
  463.           message, but the client never used it.  So, the server is
  464.           responsible for freeing the object.
  465.  
  466. ****************************************************************************/
  467. void GlobalFreeSentData(hwndServerDDE, nItem)
  468.     HWND  hwndServerDDE;
  469.     int   nItem;
  470. {
  471.     struct ADVISE * pAdvise;
  472.  
  473.     if ((pAdvise = FindAdvise(hwndServerDDE, nItem)) == NULL)
  474.         return;
  475.     pAdvise->bAwaitingAck = FALSE;
  476.     GlobalDeleteAtom(pAdvise->atomItem);
  477.     GlobalFree(pAdvise->hData);
  478.     return;
  479. }
  480.  
  481.  
  482.  
  483. /****************************************************************************
  484.  
  485.     FUNCTION: IsConvInTerminateState
  486.  
  487.     PURPOSE:  Terminate whether conversation with specified client is
  488.           in process of being terminated.
  489.  
  490. ****************************************************************************/
  491. BOOL IsConvInTerminateState(hwndServerDDE)
  492.     HWND  hwndServerDDE;
  493. {
  494.     struct CONV * pConv;
  495.  
  496.     if ((pConv = FindConv(hwndServerDDE))!=0)
  497.     return (pConv->bInClientRequestedTerminate);
  498.     else
  499.         return (FALSE);
  500. }
  501.  
  502.  
  503. /****************************************************************************
  504.  
  505.     FUNCTION: RemoveAdvise
  506.  
  507.     PURPOSE:  Cancel a hot or warm link for a specified conversation item.
  508.           If a 0 value is specified for nItem, then all hot/warm links
  509.               for the specified client are removed.
  510.  
  511. ****************************************************************************/
  512. BOOL RemoveAdvise(hwndServerDDE, nItem)
  513.     HWND  hwndServerDDE;
  514.     int   nItem;
  515. {
  516.     struct ADVISE * pAdvise;
  517.     int             nAdviseIndex;
  518.     int             nRemoveCount;
  519.  
  520.     nRemoveCount = 0;
  521.     for (nAdviseIndex = 0, pAdvise = Advise;
  522.          nAdviseIndex < nAdviseCount;
  523.          nAdviseIndex++, pAdvise++)
  524.     {
  525.         if (nRemoveCount)
  526.         {
  527.             *(pAdvise-nRemoveCount) = *pAdvise;
  528.         }
  529.     if (pAdvise->hwndServerDDE == hwndServerDDE
  530.             && (!nItem || pAdvise->nItem == nItem))
  531.         {
  532.             nRemoveCount++;
  533.         }
  534.        
  535.     }
  536.     if (nRemoveCount)
  537.     {
  538.         nAdviseCount -= nRemoveCount;
  539.         return (TRUE);
  540.     }
  541.     else
  542.     {
  543.         return (FALSE);
  544.     }
  545. }
  546.  
  547.  
  548.  
  549. /****************************************************************************
  550.  
  551.     FUNCTION: RemoveConv
  552.  
  553.     PURPOSE:  Remove conversation from conversation list, and remove
  554.           all hot/warm links associated with that conversation
  555.           from the advisory list.
  556.  
  557. ****************************************************************************/
  558. void RemoveConv(hwndServerDDE)
  559.     HWND hwndServerDDE;
  560. {
  561.     struct CONV   * pConv;
  562.     int         nConvIndex;
  563.     struct ADVISE * pAdvise;
  564.     struct ADVISE * pAdviseShift;
  565.     int             nAdviseIndex;
  566.     int             nAdviseDecrement;
  567.  
  568.     for (nConvIndex = 0, pConv = Conv;
  569.      nConvIndex < nConvCount;
  570.      nConvIndex++, pConv++)
  571.     {
  572.     if (pConv->hwndServerDDE == hwndServerDDE)
  573.             break;
  574.     }
  575.     nConvCount--;
  576.     while (nConvIndex < nConvCount)
  577.     {
  578.     *pConv = *(pConv+1);
  579.     nConvIndex++;
  580.     pConv++;
  581.     }
  582.  
  583.     /* Remove each hot/warm link */
  584.  
  585.     pAdviseShift = Advise;
  586.     nAdviseDecrement = 0;
  587.     for (nAdviseIndex = 0, pAdvise = Advise;
  588.          nAdviseIndex < nAdviseCount;
  589.          nAdviseIndex++, pAdvise++)
  590.     {
  591.     if (pAdvise->hwndServerDDE == hwndServerDDE)
  592.         {
  593.             nAdviseDecrement++;
  594.             if (pAdvise->bAwaitingAck)
  595.             { /* Destroy objects perhaps not destroyed by client */
  596.         GlobalDeleteAtom(pAdvise->atomItem);
  597.                 GlobalFree(pAdvise->hData);
  598.             }
  599.         }
  600.         else
  601.         {
  602.             *(pAdviseShift++) = *pAdvise;
  603.         }
  604.     }
  605.     nAdviseCount -= nAdviseDecrement;
  606.     return;
  607. }
  608.  
  609.  
  610.  
  611. /****************************************************************************
  612.  
  613.     FUNCTION: SetConvInTerminateState
  614.  
  615.     PURPOSE:  Set conversations's terminate state to TRUE.
  616.  
  617. ****************************************************************************/
  618. void SetConvInTerminateState(hwndServerDDE)
  619.     HWND  hwndServerDDE;
  620. {
  621.     struct CONV * pConv;
  622.  
  623.     if ((pConv = FindConv(hwndServerDDE))!=0)
  624.     pConv->bInClientRequestedTerminate = TRUE;
  625.     return;
  626. }
  627.