home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / ddeml / msngr / link.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-22  |  15.1 KB  |  498 lines

  1. /****************************** MODULE Header ******************************\
  2. * Module Name:  link.c - Messenger application - link module
  3. *
  4. * Created: 8/1/89  sanfords
  5. *
  6. * Copyright (c) 1988, 1989  Microsoft Corporation
  7. \***************************************************************************/
  8.  
  9. #include "msngr.h"
  10. #include "string.h"
  11.  
  12. extern HWND hwndMsngr;
  13. extern HPOINTER hptrLink;
  14. extern SHORT cyText;
  15. extern HAB hab;
  16. extern HSZ hszAppName;
  17. extern HSZ hszEmailName;
  18. extern NPUSERLIST gnpUL;
  19. extern PFNWP lpfnSysEFWndProc;   /* holds the system edit control proc */
  20.  
  21. typedef struct _LINKDATA {
  22.     NPUSERLIST pUserItem;
  23.     USHORT state;
  24.     HWND hwndTextIn;
  25.     char **ppszText;
  26.     char szOut[MAX_LINKSTR + 1];
  27.     USHORT cLines;
  28.     USHORT iTop;
  29. } LINKDATA;
  30. typedef LINKDATA *NPLINKDATA;
  31.  
  32. PFNWP lpfnStaticWndProc;
  33.  
  34. char **AllocTextIn(USHORT cLines);
  35. void FreeTextIn(char **ppsz, USHORT cLines);
  36. void AddTextIn(NPLINKDATA pLinkData, PSZ pszTextIn);
  37. MRESULT EXPENTRY MyTextInWndProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2);
  38.  
  39.  
  40.  
  41. /***************************** Private Function ****************************\
  42. * DESCRIPTION:
  43. *   This creates a link window with control data set up as dictated by the
  44. *   parameters given.  state incidates whether the window was created by
  45. *   user or ddeml action.
  46. *
  47. * History:      1/18/89     Created         sanfords
  48. \***************************************************************************/
  49. BOOL CreateLinkWindow(pUserItem, state)
  50. NPUSERLIST pUserItem;
  51. USHORT state;
  52. {
  53.     NPLINKDATA pLinkData;
  54.  
  55.  
  56.     if (pUserItem->hwndLink != 0) {
  57.         WinDestroyWindow(pUserItem->hwndLink);
  58.         pUserItem->hwndLink = 0;
  59.     }
  60.         
  61.     if (!(pLinkData = (NPLINKDATA)WinAllocMem(hheap, sizeof(LINKDATA)))) {
  62.         NotifyUser(SZMEMORYERROR);
  63.         return(0);
  64.     }
  65.     
  66.     pLinkData->pUserItem = pUserItem;
  67.     pLinkData->state = state;
  68.     pUserItem->hwndLink = WinLoadDlg(HWND_DESKTOP, hwndMsngr, LinkDlgProc,
  69.             0L, IDD_LINK, (PVOID)pLinkData);
  70.             
  71.     if (!WinPostMsg(pUserItem->hwndLink, UM_LINK1, 0L, 0L)) {
  72.         WinDestroyWindow(pUserItem->hwndLink);
  73.         return(FALSE);
  74.     }
  75.     return(TRUE);
  76. }
  77.  
  78.  
  79. char **AllocTextIn(cLines)
  80. USHORT cLines;
  81. {
  82.     char **ppsz, *psz;
  83.     
  84.     if (!(ppsz = (char **)WinAllocMem(hheap,
  85.             cLines * (MAX_LINKSTR + 1 + sizeof(NPSZ)))))
  86.         return(0);
  87.     psz = (char *)(ppsz + cLines);
  88.     while (cLines--) {
  89.         ppsz[cLines] = psz;
  90.         *psz = '\0';
  91.         psz += MAX_LINKSTR + 1;
  92.     }
  93.     return(ppsz);
  94. }
  95.  
  96.  
  97. void FreeTextIn(ppsz, cLines)
  98. char **ppsz;
  99. USHORT cLines;
  100. {
  101.     WinFreeMem(hheap, (NPBYTE)ppsz, cLines * (MAX_LINKSTR + 1 + sizeof(NPSZ)));
  102. }
  103.  
  104.  
  105. void AddTextIn(pLinkData, pszTextIn)
  106. NPLINKDATA pLinkData;
  107. PSZ pszTextIn;
  108. {
  109.     HPS hps;
  110.     RECTL rcl;
  111.     USHORT cchOut, cLines;
  112.     CHAR ch;
  113.     
  114.     hps = WinGetPS(pLinkData->hwndTextIn);
  115.     
  116.     cLines = 0;
  117.     WinQueryWindowRect(pLinkData->hwndTextIn, &rcl);
  118.     while (*pszTextIn) {
  119.         cchOut = WinDrawText(hps, -1, pszTextIn, &rcl, 0L, 0L,
  120.                 DT_LEFT | DT_BOTTOM | DT_WORDBREAK | DT_QUERYEXTENT);
  121.         ch = pszTextIn[cchOut];
  122.         pszTextIn[cchOut] = '\0';
  123.         lstrcpy(pLinkData->ppszText[pLinkData->iTop++], pszTextIn);
  124.         if (pLinkData->iTop == pLinkData->cLines)
  125.             pLinkData->iTop = 0;
  126.         pszTextIn[cchOut] = ch;
  127.         pszTextIn += cchOut;
  128.         while (*pszTextIn == ' ')
  129.            pszTextIn++;
  130.         cLines++;
  131.     }
  132.     WinReleasePS(hps);
  133.     WinQueryWindowRect(pLinkData->hwndTextIn, &rcl);
  134.     WinScrollWindow(pLinkData->hwndTextIn, 0, cyText * cLines,
  135.             NULL, &rcl, NULL, NULL, SW_INVALIDATERGN);
  136. }
  137.  
  138.  
  139.  
  140. /***************************** Private Function ****************************\
  141. * DESCRIPTION:
  142. *   This is a state-driven dialog which allows user linking.  At createion
  143. *   time the control data is set to contain information on who this link
  144. *   is with, and why this window was created. (user action or another user
  145. *   requesting a link.
  146. *
  147. * History:      1/18/89     Created         sanfords
  148. \***************************************************************************/
  149. MRESULT EXPENTRY LinkDlgProc(hwnd, msg, mp1, mp2)
  150. HWND hwnd;
  151. USHORT msg;
  152. MPARAM mp1;
  153. MPARAM mp2;
  154. {
  155.     register NPLINKDATA pLinkData;
  156.     register NPUSERLIST pUserItem;
  157.     char szName[MAX_NAMESTR + 1];
  158.     char szTitle[MAX_TITLESTR + 1];
  159.     SWP swp;
  160.  
  161.     if (pLinkData = (NPLINKDATA)WinQueryWindowUShort(hwnd, QWS_USER))
  162.         pUserItem = pLinkData->pUserItem;
  163.  
  164.     switch(msg) {
  165.     case WM_INITDLG:
  166.         /*
  167.          * This is required because currently, automatic ICON resource loading
  168.          * is not supported for dialogs.
  169.          */
  170.         if (hptrLink == 0) {
  171.             hptrLink = WinLoadPointer(HWND_DESKTOP, NULL, IDD_LINK);
  172.         }
  173.         WinSendMsg(hwnd, WM_SETICON, (MPARAM)hptrLink, 0L);
  174.  
  175.         /*
  176.          * we are initialized with a (near) pointer to a LINKDATA structure.
  177.          * Keep it in our window words.
  178.          */
  179.         pLinkData = (NPLINKDATA)(USHORT)mp2;
  180.         WinSetWindowUShort(hwnd, QWS_USER, (USHORT)pLinkData);
  181.         pLinkData->hwndTextIn = WinWindowFromID(hwnd, IDC_TEXTIN);
  182.  
  183.         /*
  184.          * set the output window so it is a integral multiple of cyText
  185.          * high.
  186.          */
  187.         WinQueryWindowPos(pLinkData->hwndTextIn, &swp);
  188.         swp.cy -= swp.cy % cyText;
  189.         pLinkData->cLines = swp.cy / cyText;
  190.         pLinkData->iTop = 0;
  191.         swp.fs = SWP_SIZE;
  192.         WinSetMultWindowPos(hab, &swp, 1);
  193.         
  194.         /*
  195.          * set up constants used for text output.
  196.          */
  197.         lpfnStaticWndProc = WinSubclassWindow(pLinkData->hwndTextIn,
  198.                 MyTextInWndProc);
  199.         pLinkData->cLines = swp.cy / cyText;
  200.         pLinkData->ppszText = AllocTextIn(pLinkData->cLines);
  201.         
  202.         /*
  203.          * subclass the edit control so that enter keys send us a message.
  204.          */
  205.         lpfnSysEFWndProc =
  206.                 WinSubclassWindow(WinWindowFromID(hwnd, IDC_EF_TEXTOUT),
  207.                 EnhancedEFWndProc);
  208.                 
  209.         WinSendDlgItemMsg(hwnd, IDC_EF_TEXTOUT, EM_SETTEXTLIMIT,
  210.                 MPFROMSHORT(MAX_LINKSTR), 0L);
  211.  
  212.         /*
  213.          * return 1 so we don't get the focus - we are still invisible!
  214.          */
  215.         return(1);
  216.         break;
  217.  
  218.     case WM_DESTROY:
  219.         /*
  220.          *      Terminate advise loop.
  221.          *      Destroy connection if made
  222.          *          advise loops first.
  223.          *      free control data
  224.          */
  225.         if (pUserItem->hConvLink) {
  226.             if (pLinkData->state == LNKST_LINKED) {
  227.                 DdeClientXfer(0, 0L, pUserItem->hConvLink,
  228.                         hszEmailName, 
  229.                         DDEFMT_TEXT, XTYP_ADVSTOP, ulTimeout, NULL);
  230.             }
  231.             DdeDisconnect(pUserItem->hConvLink);
  232.             pUserItem->hConvLink = 0;
  233.         }
  234.         FreeTextIn(pLinkData->ppszText, pLinkData->cLines);
  235.         WinFreeMem(hheap, (NPBYTE)pLinkData, sizeof(LINKDATA));
  236.         pUserItem->hwndLink = 0;
  237.         break;
  238.  
  239.     case UM_LINK1:
  240.         /*
  241.          * connect on link channel - topic = server name.
  242.          */
  243.         if (!pUserItem->hConvLink && !(pUserItem->hConvLink =
  244.                 DdeConnect(hszAppName, pUserItem->hsz, NULL, (HAPP)mp1))) {
  245.             if (pLinkData->state == LNKST_USERSTART) 
  246.                 NotifyUser(SZCANTLINK);
  247.             return(FALSE);
  248.         }
  249.         
  250.         if (pLinkData->state == LNKST_USERSTART) {
  251.             return(WinSendMsg(hwnd, UM_DOADVSTART, 0L, 0L));
  252.         } else {
  253.             /*
  254.              * We were started by a ddeml advise message - return now
  255.              * and post an advise start message to ourselves so we send
  256.              * it AFTER we returned from his advise.
  257.              */
  258.             WinPostMsg(hwnd, UM_DOADVSTART, 0L, 0L);
  259.             return(TRUE);
  260.         }
  261.         break;
  262.  
  263.     case UM_DOADVSTART:
  264.         /*
  265.          * Its time to start the advise loop...return fSuccess 
  266.          *
  267.          * Item = client name.
  268.          */
  269.         if (DdeClientXfer(0, 0L, pUserItem->hConvLink, hszEmailName,
  270.                 DDEFMT_TEXT, XTYP_ADVSTART, ulTimeout, NULL)) {
  271.             DdeGetHszString(hszEmailName, szName, MAX_NAMESTR + 1L);
  272.             lstrcat(szTitle, szName, SZMSGLINKWITH);
  273.             DdeGetHszString(pUserItem->hsz, szName, MAX_NAMESTR + 1L);
  274.             lstrcat(szTitle, szTitle, szName);
  275.             WinSetDlgItemText(hwnd, FID_TITLEBAR, szTitle);
  276.             if (pLinkData->state == LNKST_DMGSTART) {
  277.                 pLinkData->state = LNKST_LINKED;
  278.                 WinSetDlgItemText(hwnd, IDC_INFO, SZLINKED);
  279.             }
  280.             WinShowWindow(hwnd, TRUE);
  281.             return(TRUE);
  282.  
  283.         } else {
  284.             if (pLinkData->state == LNKST_USERSTART)
  285.                 MyPostError(DdeGetLastError());
  286.             else
  287.                 /*
  288.                  * destroy ouselves lest we have an invisible link window
  289.                  * hanging around.
  290.                  */
  291.                 WinDestroyWindow(hwnd);
  292.             return(FALSE);
  293.         }
  294.         break;
  295.  
  296.     case UM_ADVRCVD:
  297.         if (pLinkData->state == LNKST_USERSTART) {
  298.             pLinkData->state = LNKST_LINKED;
  299.             WinSetDlgItemText(hwnd, IDC_INFO, SZLINKED);
  300.         }
  301.         break;
  302.  
  303.     case UM_LINKDATAIN:
  304.         AddTextIn(pLinkData, (PSZ)mp1);
  305.         break;
  306.  
  307.     case UM_BREAKLINK:
  308.         if (pLinkData->state == LNKST_LINKED) {
  309.             NotifyUser(SZLINKBROKEN);
  310.             if (WinIsWindow(hab, hwnd))
  311.                 WinDestroyWindow(hwnd);
  312.         }
  313.         break;
  314.  
  315.     case WM_WINDOWPOSCHANGED:
  316.         /*
  317.          * hide the Edit control when minimized since it messes up the icon.
  318.          */
  319.         if ((LONG)mp2 & AWP_MINIMIZED)
  320.             WinShowWindow(WinWindowFromID(hwnd, IDC_EF_TEXTOUT), FALSE);
  321.         else if ((LONG)mp2 & AWP_RESTORED)
  322.             WinShowWindow(WinWindowFromID(hwnd, IDC_EF_TEXTOUT), TRUE);
  323.         return(WinDefDlgProc(hwnd, msg, mp1, mp2));
  324.         break;
  325.         
  326.     case WM_COMMAND:
  327.         switch (LOUSHORT(mp1)) {
  328.         case IDC_TERMINATE:
  329.             if (pLinkData->state == LNKST_LINKED) {
  330.                 pLinkData->state = LNKST_UNLINKED;
  331.                 DdeClientXfer(0, 0L, pUserItem->hConvLink, hszEmailName,
  332.                         DDEFMT_TEXT, XTYP_ADVSTOP, ulTimeout, NULL);
  333.             }
  334.             WinDestroyWindow(hwnd);
  335.             break;
  336.         }
  337.         break;
  338.  
  339.     case ENHAN_ENTER:
  340.         /*
  341.          * when the user hits the enter key, it will be passed from the
  342.          * entryfield to here and we will send it to the linkee.
  343.          */
  344.         WinQueryDlgItemText(hwnd, IDC_EF_TEXTOUT, MAX_LINKSTR + 1,
  345.                 pLinkData->szOut);
  346.         WinSetDlgItemText(hwnd, IDC_EF_TEXTOUT, "");
  347.         if (pLinkData->state == LNKST_LINKED)
  348.             /*
  349.              * we postadvise to OUR server which is talking to HIS client
  350.              * which has the topic being OUR name and the item being HIS.
  351.              * This results in a UM_LINKDATAOUT being sent to us.
  352.              */
  353.             DdePostAdvise(hszEmailName, pUserItem->hsz);
  354.         break;
  355.  
  356.     case UM_LINKDATAOUT:
  357.         /*
  358.          * returns hDmgData filled.
  359.          */
  360.         if (pLinkData->state == LNKST_LINKED) {
  361.             return(DdePutData(pLinkData->szOut,
  362.                     (ULONG)(lstrlen(pLinkData->szOut) + 1), 0L,
  363.                     pUserItem->hsz, DDEFMT_TEXT, 0));
  364.         }
  365.         break;
  366.  
  367.     default:
  368.         return(WinDefDlgProc(hwnd, msg, mp1, mp2));
  369.         break;
  370.     }
  371.     return(0);
  372. }
  373.  
  374.  
  375.  
  376.  
  377. /***************************** Private Function ****************************\
  378. * DESCRIPTION:
  379. *   This function gains control whenever externaly trigered data transfers
  380. *   are sent to the hszEmailName topic.
  381. *
  382. * History:      1/17/89     Created         sanfords
  383. \***************************************************************************/
  384. HDMGDATA LinkXfer(pXferInfo, hszPartner)
  385. PXFERINFO pXferInfo;
  386. HSZ hszPartner;
  387. {
  388.     NPUSERLIST pUserItem;
  389.     char szTextIn[MAX_LINKSTR + 1];
  390.  
  391.     /*
  392.      * always allow creation of servers on this topic.
  393.      */
  394.     if (pXferInfo->usType == XTYP_INIT)
  395.         return(TRUE);
  396.  
  397.     /*
  398.      * we only allow text
  399.      */
  400.     if (pXferInfo->usFmt != DDEFMT_TEXT)
  401.         return(0);
  402.  
  403.     /*
  404.      * if he's gone, this should never happen.
  405.      */
  406.     if (!(pUserItem = FindUser(gnpUL, hszPartner))) {
  407.         NotifyUser(SZINTERNALERROR);
  408.         return(0);
  409.     }
  410.  
  411.     if (pXferInfo->usType == XTYP_ADVSTART) {
  412.         /*
  413.          * link Advise startup - if no hwndLink, he started it, we must
  414.          * create a link window and a counter advise loop.  If we do
  415.          * have a hwndLink, we started it and it is his counter advise
  416.          * link request.
  417.          */
  418.         if (!WinIsWindow(hab, pUserItem->hwndLink)) {
  419.             return((HDMGDATA)CreateLinkWindow(pUserItem, LNKST_DMGSTART));
  420.         } else {
  421.             WinSendMsg(pUserItem->hwndLink, UM_ADVRCVD, 0L, 0L);
  422.             return(DDE_FACK);
  423.         }
  424.     }
  425.  
  426.     /*
  427.      * The rest of these are only applicable if we are in an active link
  428.      * situation, so quit if no link window is present.
  429.      */
  430.     if (!WinIsWindow(hab, pUserItem->hwndLink)) 
  431.         return(0);
  432.  
  433.     switch (pXferInfo->usType) {
  434.     case XTYP_ADVDATA:
  435.         /*
  436.          * incomming link data
  437.          */
  438.         DdeGetData(pXferInfo->hDmgData, szTextIn, (ULONG)(MAX_LINKSTR + 1), 0L);
  439.         DdeFreeData(pXferInfo->hDmgData);
  440.         WinSendMsg(pUserItem->hwndLink, UM_LINKDATAIN, (MPARAM)szTextIn, 0L);
  441.         return(DDE_FACK);
  442.         break;
  443.  
  444.     case XTYP_REQUEST:
  445.     case XTYP_ADVREQ:
  446.         /*
  447.          * Outgoing link data
  448.          */
  449.         return((HDMGDATA)WinSendMsg(pUserItem->hwndLink, UM_LINKDATAOUT, 0L, 0L));
  450.         break;
  451.  
  452.     case XTYP_ADVSTOP:
  453.         WinSendMsg(pUserItem->hwndLink, UM_BREAKLINK, 0L, 0L);
  454.         return(TRUE);
  455.         break;
  456.     }
  457.     return(0);
  458. }
  459.  
  460.  
  461.  
  462. MRESULT EXPENTRY MyTextInWndProc(hwnd, msg, mp1, mp2)
  463. HWND hwnd;
  464. USHORT msg;
  465. MPARAM mp1;
  466. MPARAM mp2;
  467. {
  468.     register NPLINKDATA pLinkData;
  469.     RECTL rcl;
  470.     HPS hps;
  471.     USHORT iLine, cLines;
  472.     
  473.     switch (msg) {
  474.     case WM_PAINT:
  475.         hps = WinBeginPaint(hwnd, NULL, &rcl);
  476.         pLinkData = (NPLINKDATA)WinQueryWindowUShort(
  477.                 WinQueryWindow(hwnd, QW_PARENT, FALSE), QWS_USER);
  478.         WinQueryWindowRect(hwnd, &rcl);
  479.         rcl.yBottom = rcl.yTop - cyText;
  480.         
  481.         iLine = pLinkData->iTop;
  482.         cLines = pLinkData->cLines;
  483.         while (cLines--) {
  484.             WinDrawText(hps, -1, pLinkData->ppszText[iLine++], &rcl, 0L, 0L,
  485.                     DT_LEFT | DT_VCENTER | DT_ERASERECT | DT_TEXTATTRS);
  486.             if (iLine == pLinkData->cLines)
  487.                 iLine = 0;
  488.             WinOffsetRect(hab, &rcl, 0, -cyText);
  489.         }
  490.         WinEndPaint(hps);
  491.         break;
  492.  
  493.     default:
  494.         return((*lpfnStaticWndProc)(hwnd, msg, mp1, mp2));
  495.     }
  496. }
  497.  
  498.