home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / win_lrn / dde / ddeapp / ddeapp.c next >
Encoding:
C/C++ Source or Header  |  1988-10-21  |  42.1 KB  |  1,616 lines

  1. /*
  2.  *      ddeapp.c
  3.  *
  4.  *      This is a dummy application used to test the DDE capabilities
  5.  *      of Microsoft Excel.
  6.  *
  7.  */
  8.  
  9. #include <windows.h>
  10. #include "ddeapp.h"
  11.  
  12. #define GMEM_DDESHARE 0x2000
  13. #define EXCEL
  14.  
  15. #ifdef EXCEL
  16. #define szAppDef "Excel"
  17. #define szDocDef "Sheet1"
  18. #define szRefDef "r1c1:c1c2"
  19. #define szDataDef "42"
  20. #endif
  21.  
  22. #ifdef OPUS
  23. #define szAppDef "Opus"
  24. #define szDocDef "opus.doc"
  25. #define szRefDef "bkmk1"
  26. #define szDataDef "Foo bar."
  27. #endif
  28.  
  29. #ifdef FISH
  30. #define szAppDef "Fish"
  31. #define szDocDef "sub"
  32. #define szRefDef "bkmk1"
  33. #define szDataDef "[l]"
  34. #endif
  35.  
  36. #ifndef FISH
  37. #ifndef OPUS
  38. #ifndef EXCEL
  39. #define szAppDef ""
  40. #define szDocDef ""
  41. #define szRefDef ""
  42. #define szDataDef ""
  43. #endif
  44. #endif
  45. #endif
  46.  
  47.  
  48. long far pascal DdeWndProc(HWND, unsigned, int, long);
  49. BOOL far pascal InitiateDlg(HWND, unsigned, int, long);
  50. BOOL far pascal ExecuteDlg(HWND, unsigned, int, long);
  51. BOOL far pascal PokeDlg(HWND, unsigned, int, long);
  52. BOOL far pascal TermDlg(HWND, unsigned, int, long);
  53. BOOL far pascal RequestDlg(HWND, unsigned, int, long);
  54. BOOL far pascal UnadviseDlg(HWND, unsigned, int, long);
  55.  
  56. void PostClientMsg(int, int, ATOM, int);
  57. void ChnlBox(HWND, int);
  58. void ClipFmtBox(HWND,int);
  59.  
  60. BOOL FInit(int);
  61. BOOL FGetAck(HWND);
  62. int  IclListBox(HWND,int);
  63.  
  64.  
  65. HANDLE  hinstDDE;
  66. HWND    hwndDDE;
  67. HBRUSH  hbrBack;
  68. HCURSOR hcrsWait;
  69. HCURSOR hcrsArrow;
  70.  
  71. /* supported clipboard formats */
  72. #define szClipRTF   "Rich Text Format"
  73. #define szClipLink  "Link"
  74. #define szClipCSV   "Csv"
  75. #define szClipBitPrinter  "Printer_Bitmap"
  76. #define szClipMetaPrinter "Printer_Picture"
  77.  
  78. #define icfMax 9
  79. #define icfRTF 5
  80. #define icfCSV 6
  81. #define icfBitPrinter 7
  82. #define icfMetaPrinter 8
  83. int rgcf[icfMax] = {
  84.         CF_TEXT,
  85.         CF_SYLK,
  86.         CF_DIF,
  87.         CF_BITMAP,
  88.         CF_METAFILEPICT
  89. };
  90.  
  91. int  cfLink;
  92. int  iRadioButton, iRadioButtonTemp;
  93. int  iResult, iAck;
  94. BOOL fInInitiate = FALSE;
  95. HWND hwndLink;
  96.  
  97. char szApp[256]  = szAppDef;
  98. char szDoc[256]  = szDocDef;
  99. char szRef[256]  = szRefDef;
  100. char szData[245] = szDataDef;
  101.  
  102. int cfCur;
  103. int iclCur;
  104.  
  105. PLCL **hplcl;           /* channel array */
  106. PLDL **hpldl;           /* dependent link array */
  107.  
  108.  
  109. /*      WinMain
  110.  *
  111.  *      Main entry point for DDE dummy application.
  112.  *
  113.  *      Arguments:
  114.  *              hinst
  115.  *              hinstPrev
  116.  *              lpszCmdLine
  117.  *              sw
  118.  *
  119.  *      Returns:
  120.  *
  121.  */
  122. int far pascal WinMain(hinst, hinstPrev, lpszCmdLine, sw)
  123. HANDLE hinst;
  124. HANDLE hinstPrev;
  125. char far *lpszCmdLine;
  126. int sw;
  127. {
  128.    MSG msg;
  129.    PL **HplInit();
  130.  
  131.    hinstDDE = hinst;
  132.  
  133.    if (!FInit(sw))
  134.            return(0);
  135.  
  136.    hplcl = (PLCL **)HplInit(sizeof(CL));
  137.    hpldl = (PLDL **)HplInit(sizeof(DL));
  138.  
  139.    rgcf[icfRTF] = RegisterClipboardFormat((LPSTR)szClipRTF);
  140.    cfLink       = RegisterClipboardFormat((LPSTR)szClipLink);
  141.    rgcf[icfCSV] = RegisterClipboardFormat((LPSTR)szClipCSV);
  142.    rgcf[icfBitPrinter] = RegisterClipboardFormat((LPSTR)szClipBitPrinter);
  143.    rgcf[icfMetaPrinter] = RegisterClipboardFormat((LPSTR)szClipMetaPrinter);
  144.    while (GetMessage((MSG far *)&msg, NULL, 0, 0)) {
  145.            TranslateMessage((MSG far *)&msg);
  146.            DispatchMessage((MSG far *)&msg);
  147.    }
  148.  
  149.    return(msg.wParam);
  150. }
  151.  
  152.  
  153. /* ----------------------------------------------------- */
  154. void Error(sz)
  155. char *sz;
  156. {
  157.    MessageBeep(MB_OK|MB_ICONHAND|MB_APPLMODAL);
  158.    MessageBox(hwndDDE, (LPSTR)sz, (LPSTR)"DDE failure", MB_OK|MB_ICONHAND|MB_APPLMODAL);
  159. }
  160.  
  161.  
  162. /* -----------------------------------------------------
  163.  *      CchSzLen
  164.  *
  165.  *      Returns the length of a null-terminated string.
  166.  *
  167.  *      Arguments:
  168.  *              sz
  169.  *
  170.  *      Returns:
  171.  *              length of the string
  172.  */
  173. int CchSzLen(sz)
  174. char far *sz;
  175. {
  176.    int cch;
  177.  
  178.    cch = 0;
  179.    while (*sz++)
  180.            cch++;
  181.    return(cch);
  182. }
  183.  
  184.  
  185. /* ----------------------------------------------------
  186.  *      bltbx
  187.  *
  188.  *      Far block transfer.
  189.  *
  190.  *      Arguments:
  191.  *              lpbFrom         source buffer
  192.  *              lpbTo           destination buffer
  193.  *              cb              number of bytes to move
  194.  *
  195.  *      Returns:
  196.  *              nothing.
  197.  *
  198.  *      Warning:
  199.  *              does not handle over-lapping transfer!
  200.  */
  201. void bltbx(lpbFrom, lpbTo, cb)
  202. BYTE far *lpbFrom;
  203. BYTE far *lpbTo;
  204. unsigned cb;
  205. {
  206.         while (cb--)
  207.                 *lpbTo++ = *lpbFrom++;
  208. }
  209.  
  210.  
  211. /* -----------------------------------------------------
  212.  *      FInit
  213.  *
  214.  *      Initializes the window app.
  215.  *
  216.  *      Arguments:
  217.  *              sw              type of ShowWindow call to make on
  218.  *                              first window created.
  219.  *
  220.  *      Returns:
  221.  *              TRUE if successful
  222.  */
  223. BOOL FInit(sw)
  224. int sw;
  225. {
  226.    WNDCLASS cls;
  227.    HDC hdc;
  228.    int dxScreen, dyScreen;
  229.  
  230. /* register window class */
  231.  
  232.    hbrBack   = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  233.    hcrsArrow = LoadCursor(NULL, IDC_ARROW);
  234.    hcrsWait  = LoadCursor(NULL, IDC_WAIT);
  235.  
  236.    cls.lpszClassName = (LPSTR)"DdeApp";
  237.    cls.lpfnWndProc   = DdeWndProc;
  238.    cls.hInstance     = hinstDDE;
  239.    cls.hIcon         = LoadIcon(NULL, IDI_HAND);
  240.    cls.hCursor       = NULL;
  241.    cls.lpszMenuName  = MAKEINTRESOURCE(mbDde);
  242.    cls.hbrBackground = hbrBack;
  243.    cls.style         = 0;
  244.    cls.cbClsExtra    = cls.cbWndExtra = 0;
  245.    if (!RegisterClass((WNDCLASS far *)&cls))
  246.            return(FALSE);
  247.  
  248. /* create initial tiled window */
  249.  
  250.    hdc = CreateDC((LPSTR)"DISPLAY", NULL, NULL, NULL);
  251.    dxScreen = GetDeviceCaps(hdc, HORZRES);
  252.    dyScreen = GetDeviceCaps(hdc, VERTRES);
  253.    DeleteDC(hdc);
  254.    hwndDDE = CreateWindow((LPSTR)"DdeApp",
  255.                    (LPSTR)"Acme DDE Application",
  256.                    WS_OVERLAPPEDWINDOW,
  257.                    0, 0, dxScreen/2, dyScreen/4,
  258.                    NULL, NULL, hinstDDE, NULL);
  259.    ShowWindow(hwndDDE, sw);
  260.  
  261.    return(TRUE);
  262. }
  263.  
  264.  
  265. /* ----------------------------------------------------- */
  266.  
  267. BOOL far pascal InitiateDlg(hdlg, wm, wParam, lParam)
  268. HWND hdlg;
  269. unsigned wm;
  270. int wParam;
  271. long lParam;
  272. {
  273.     switch (wm) {
  274.     case WM_INITDIALOG:
  275.             SetDlgItemText(hdlg, idtxtApp, (LPSTR)szApp);
  276.             SetDlgItemText(hdlg, idtxtDoc, (LPSTR)szDoc);
  277.             break;
  278.     case WM_COMMAND:
  279.             switch (wParam) {
  280.             case IDOK:
  281.                     GetDlgItemText(hdlg, idtxtApp, (LPSTR)szApp, sizeof(szApp));
  282.                     GetDlgItemText(hdlg, idtxtDoc, (LPSTR)szDoc, sizeof(szDoc));
  283.                     EndDialog(hdlg, TRUE);
  284.                     break;
  285.             case IDCANCEL:
  286.                     EndDialog(hdlg, FALSE);
  287.                     break;
  288.             }
  289.     default:
  290.             return(FALSE);
  291.     }
  292.     return(TRUE);
  293. }
  294.  
  295. /* ----------------------------------------------------- */
  296.  
  297. BOOL far pascal RequestDlg(hdlg, wm, wParam, lParam)
  298. HWND hdlg;
  299. unsigned wm;
  300. int wParam;
  301. long lParam;
  302. {
  303.    HWND hctl;
  304.    int icf;
  305.  
  306.    switch (wm) {
  307.    case WM_INITDIALOG:
  308.            ChnlBox(hdlg, idlboxChnl);
  309.            ClipFmtBox(hdlg, idlboxFmt);
  310.            SetDlgItemText(hdlg, idtxtRef, (LPSTR)szRef);
  311.            SendDlgItemMessage(hdlg, idlboxChnl, LB_SETCURSEL, 0, 0L);
  312.            return(TRUE);
  313.    case WM_COMMAND:
  314.            switch (wParam) {
  315.            case IDOK:
  316.                    if ((iclCur = IclListBox(hdlg, idlboxChnl)) == -1)
  317.                            return(TRUE);
  318.                    if ((icf = SendMessage(GetDlgItem(hdlg, idlboxFmt),
  319.                                    LB_GETCURSEL, 0, 0L)) == -1)
  320.                            return(TRUE);
  321.                    GetDlgItemText(hdlg, idtxtRef, (LPSTR)szRef, sizeof(szRef));
  322.                    cfCur = rgcf[icf];
  323.                    EndDialog(hdlg, TRUE);
  324.                    return(TRUE);
  325.            case IDCANCEL:
  326.                    EndDialog(hdlg, FALSE);
  327.                    return(TRUE);
  328.            default:
  329.                    return(FALSE);
  330.            }
  331.    default:
  332.            return(FALSE);
  333.    }
  334.    return(TRUE);
  335. }
  336.  
  337.  
  338. /* ----------------------------------------------------- */
  339. void LinkBox(hdlg, idlbox, icl)
  340. HWND hdlg;
  341. int idlbox;
  342. int icl;
  343. {
  344.     int idl;
  345.     PLDL *ppldl;
  346.     HWND hctl;
  347.     char sz[256];
  348.  
  349.     hctl = GetDlgItem(hdlg, idlbox);
  350.     SendMessage(hctl, LB_RESETCONTENT, 0, 0L);
  351.     ppldl = (PLDL *)LocalLock((HANDLE)hpldl);
  352.     for (idl = 0; idl < ppldl->idlMax; idl++) {
  353.         if (!ppldl->rgdl[idl].fUsed || ppldl->rgdl[idl].icl != icl)
  354.                 continue;
  355.         GlobalGetAtomName(ppldl->rgdl[idl].atomRef, (LPSTR)sz, sizeof(sz));
  356.         SendMessage(hctl, LB_ADDSTRING, 0, (DWORD)(LPSTR)sz);
  357.         SendMessage(hctl, LB_GETCOUNT, 0, 0L);
  358.     }
  359.     LocalUnlock((HANDLE)hpldl);
  360. }
  361.  
  362.  
  363. /* ----------------------------------------------------- */
  364.  
  365. BOOL far pascal UnadviseDlg(hdlg, wm, wParam, lParam)
  366. HWND hdlg;
  367. unsigned wm;
  368. int wParam;
  369. long lParam;
  370. {
  371.     HWND hctl;
  372.     int il;
  373.  
  374.     switch (wm) {
  375.     case WM_INITDIALOG:
  376.             ChnlBox(hdlg, idlboxChnl);
  377.             SendDlgItemMessage(hdlg, idlboxChnl, LB_SETCURSEL, 0, 0L);
  378.             return(TRUE);
  379.     case WM_COMMAND:
  380.             switch (wParam) {
  381.             case IDOK:
  382.                     if ((iclCur = IclListBox(hdlg, idlboxChnl)) == -1)
  383.                             return(TRUE);
  384.                     if ((il = SendMessage(hctl = GetDlgItem(hdlg, idlboxRef),
  385.                                     LB_GETCURSEL, 0, 0L)) == -1)
  386.                             return(TRUE);
  387.                     SendMessage(hctl, LB_GETTEXT, il, (DWORD)(LPSTR)szRef);
  388.                     EndDialog(hdlg, TRUE);
  389.                     return(TRUE);
  390.             case IDCANCEL:
  391.                     EndDialog(hdlg, FALSE);
  392.                     return(TRUE);
  393.             case idlboxChnl:
  394.                     if (HIWORD(lParam) == LBN_SELCHANGE) {
  395.                             if ((iclCur = IclListBox(hdlg, idlboxChnl)) == -1)
  396.                                     return(TRUE);
  397.                             LinkBox(hdlg, idlboxRef, iclCur);
  398.                             return(TRUE);
  399.                     }
  400.                     return(FALSE);
  401.             default:
  402.                     return(FALSE);
  403.             }
  404.         default:
  405.             return(FALSE);
  406.     }
  407.     return(TRUE);
  408. }
  409.  
  410.  
  411. /* ----------------------------------------------------- */
  412.  
  413. BOOL far pascal ExecuteDlg(hdlg, wm, wParam, lParam)
  414. HWND hdlg;
  415. unsigned wm;
  416. int wParam;
  417. long lParam;
  418. {
  419.    switch (wm) {
  420.    case WM_INITDIALOG:
  421.            ChnlBox(hdlg, idlboxChnl);
  422.            SetDlgItemText(hdlg, idtxtRef, (LPSTR)szRef);
  423.            SendDlgItemMessage(hdlg, idlboxChnl, LB_SETCURSEL, 0, 0L);
  424.            break;
  425.    case WM_COMMAND:
  426.            switch (wParam) {
  427.            case IDOK:
  428.                    GetDlgItemText(hdlg, idtxtRef, (LPSTR)szRef, sizeof(szRef));
  429.                    if ((iclCur = IclListBox(hdlg, idlboxChnl)) == -1)
  430.                            return(TRUE);
  431.                    EndDialog(hdlg, TRUE);
  432.                    return(TRUE);
  433.            case IDCANCEL:
  434.                    EndDialog(hdlg, FALSE);
  435.                    return(TRUE);
  436.            }
  437.    default:
  438.            return(FALSE);
  439.    }
  440.    return(TRUE);
  441. }
  442.  
  443. /* ----------------------------------------------------- */
  444.  
  445. BOOL far pascal PokeDlg(hdlg, wm, wParam, lParam)
  446. HWND hdlg;
  447. unsigned wm;
  448. int wParam;
  449. long lParam;
  450. {
  451.    switch (wm) {
  452.    case WM_INITDIALOG:
  453.            ChnlBox(hdlg, idlboxChnl);
  454.            SetDlgItemText(hdlg, idtxtRef, (LPSTR)szRef);
  455.  
  456.            CheckRadioButton(hdlg, idradioText, idradioFile, idradioText);
  457.            iRadioButtonTemp = idradioText;
  458.  
  459.            /* file is not implemented so it is disabled */
  460.            EnableWindow( GetDlgItem(hdlg,idradioFile), FALSE );
  461.  
  462.            SendDlgItemMessage(hdlg, idlboxChnl, LB_SETCURSEL, 0, 0L);
  463.  
  464.            break;
  465.  
  466.    case WM_COMMAND:
  467.            switch (wParam) {
  468.            case IDOK:
  469.  
  470.                   iResult = GetDlgItemText(hdlg, idtxtData,
  471.                                            (LPSTR)szData, sizeof(szData));
  472.                   iResult = GetDlgItemText(hdlg, idtxtRef,
  473.                                            (LPSTR)szRef, sizeof(szRef));
  474.                   if ((iclCur = IclListBox(hdlg, idlboxChnl)) == -1)
  475.                      return(TRUE);
  476.  
  477.                   iRadioButton = iRadioButtonTemp;
  478.  
  479.                   /* verify contents of Poke message */
  480.                   /* if the button is csv
  481.                         and the ref is < 5 characters
  482.                         then if the data has a comma in it
  483.                                 then display a warning message
  484.                    */
  485.  
  486.                   if ( iRadioButtonTemp == idradioCsv && iResult<5 ) {
  487.                      /* check for comma in data */
  488.                      MessageBox( GetFocus(), "Ref may be too small",
  489.                                              "Warning", MB_OK);
  490.  
  491.                      }
  492.  
  493.                    EndDialog(hdlg, TRUE);
  494.                    return(TRUE);
  495.            case IDCANCEL:
  496.                    EndDialog(hdlg, FALSE);
  497.                    return(TRUE);
  498.  
  499.            case idradioText:
  500.            case idradioCsv:
  501.            case idradioFile:
  502.                    CheckRadioButton(hdlg, idradioText, idradioFile,
  503.                       (iRadioButtonTemp = wParam));
  504.                    return(TRUE);
  505.                    break;
  506.  
  507.            }
  508.    default:
  509.            return(FALSE);
  510.    }
  511.    return(TRUE);
  512. }
  513.  
  514.  
  515.  
  516.  
  517.  
  518. /* ----------------------------------------------------- */
  519.  
  520. BOOL far pascal TermDlg(hdlg, wm, wParam, lParam)
  521. HWND hdlg;
  522. unsigned wm;
  523. int wParam;
  524. long lParam;
  525. {
  526.    switch (wm) {
  527.    case WM_INITDIALOG:
  528.            ChnlBox(hdlg, idlboxChnl);
  529.            SendDlgItemMessage(hdlg, idlboxChnl, LB_SETCURSEL, 0, 0L);
  530.            break;
  531.    case WM_COMMAND:
  532.            switch (wParam) {
  533.            case IDOK:
  534.                    if ((iclCur = IclListBox(hdlg, idlboxChnl)) == -1)
  535.                            return(TRUE);
  536.                    EndDialog(hdlg, TRUE);
  537.                    break;
  538.            case IDCANCEL:
  539.                    EndDialog(hdlg, FALSE);
  540.                    break;
  541.            default:
  542.                    break;
  543.            }
  544.    default:
  545.            return(FALSE);
  546.    }
  547.    return(TRUE);
  548. }
  549.  
  550.  
  551. /* -----------------------------------------------------
  552.  *      RemoveLinks
  553.  *
  554.  *      Removes all a channel's links from our data structures.
  555.  *
  556.  *      Arguments:
  557.  *              icl             channel to remove links from
  558.  *
  559.  *      Returns:
  560.  *              nothing.
  561.  */
  562. void RemoveLinks(icl)
  563. int icl;
  564. {
  565.     int idl;
  566.     PLDL *ppldl;
  567.  
  568.     ppldl = (PLDL *)LocalLock((HANDLE)hpldl);
  569.     for (idl = 0; idl < ppldl->idlMax; idl++) {
  570.             if (ppldl->rgdl[idl].fUsed && ppldl->rgdl[idl].icl == icl)
  571.                     ppldl->rgdl[idl].fUsed = FALSE;
  572.     }
  573.     LocalUnlock((HANDLE)hpldl);
  574. }
  575.  
  576.  
  577.  
  578. /* -----------------------------------------------------
  579.  *      AddPl
  580.  *
  581.  *      Adds an item to a PL
  582.  *
  583.  *      Arguments:
  584.  *              hpl
  585.  *              pbData
  586.  *
  587.  *      Returns:
  588.  *              Nothing.
  589.  */
  590. void AddPl(hpl, pbData)
  591. PL **hpl;
  592. BYTE *pbData;
  593. {
  594.    PL *ppl;
  595.    BYTE *pb;
  596.    int cbItem;
  597.    int i, iMax;
  598.    int dAlloc;
  599.  
  600.    ppl = (PL *)LocalLock((HANDLE)hpl);
  601.    cbItem = ppl->cbItem;
  602.    iMax = ppl->iMax;
  603.    for (i = 0, pb = ppl->rg; i < iMax; i++, pb += cbItem) {
  604.            if (!*(int *)pb)
  605.                    goto Return;
  606.    }
  607.    dAlloc = ppl->dAlloc;
  608.    LocalUnlock((HANDLE)hpl);
  609.    LocalReAlloc((HANDLE)hpl, sizeof(PL)-1 + (iMax + dAlloc) * cbItem,
  610.                    LMEM_MOVEABLE|LMEM_ZEROINIT);
  611.    ppl = (PL *)LocalLock((HANDLE)hpl);
  612.    ppl->iMax = iMax + dAlloc;
  613.    pb = &ppl->rg[cbItem * iMax];
  614. Return:
  615.    bltbx((BYTE far *)pbData, (BYTE far *)pb, cbItem);
  616.    *(int *)pb = TRUE;
  617.    LocalUnlock((HANDLE)hpl);
  618. }
  619.  
  620.  
  621.  
  622. /* -----------------------------------------------------
  623.  *      HplInit
  624.  *
  625.  *      Initializes a plex
  626.  *
  627.  *      Arguments:
  628.  *              cbItem          sizeof item to put in plex
  629.  *
  630.  *      Returns:
  631.  *              handle to new plex
  632.  */
  633. PL **HplInit(cbItem)
  634. int cbItem;
  635. {
  636.    PL **hpl, *ppl;
  637.  
  638.    hpl = (PL **)LocalAlloc(LMEM_MOVEABLE|LMEM_ZEROINIT, sizeof(PL)-1);
  639.    ppl = (PL *)LocalLock((HANDLE)hpl);
  640.    ppl->iMax = 0;
  641.    ppl->dAlloc = 5;
  642.    ppl->cbItem = cbItem;
  643.    LocalUnlock((HANDLE)hpl);
  644.    return(hpl);
  645. }
  646.  
  647.  
  648. /* -------------------------------------------------
  649.  *      RemovePl
  650.  *
  651.  *      Removes an item from a plex
  652.  *
  653.  *      Arguments:
  654.  *              hpl
  655.  *              i
  656.  *
  657.  *      Returns:
  658.  *              nothing.
  659.  */
  660. void RemovePl(hpl, i)
  661. PL **hpl;
  662. int i;
  663. {
  664.    PL *ppl;
  665.  
  666.    ppl = (PL *)LocalLock((HANDLE)hpl);
  667.    *(int *)&ppl->rg[i * ppl->cbItem] = FALSE;
  668.    LocalUnlock((HANDLE)hpl);
  669. }
  670.  
  671.  
  672. /* ----------------------------------------------------
  673.  *      GetPl
  674.  *
  675.  *      gets an item from a plex
  676.  *
  677.  *      Arguments:
  678.  *              hpl
  679.  *              i
  680.  *              pb
  681.  *
  682.  *      Returns:
  683.  *              nothing.
  684.  */
  685. void GetPl(hpl, i, pb)
  686. PL **hpl;
  687. int i;
  688. BYTE *pb;
  689. {
  690.     PL *ppl;
  691.  
  692.     ppl = (PL *)LocalLock((HANDLE)hpl);
  693.     bltbx((BYTE far *)&ppl->rg[i * ppl->cbItem], (BYTE far *)pb, ppl->cbItem);
  694.     LocalUnlock((HANDLE)hpl);
  695. }
  696.  
  697.  
  698. /* -----------------------------------------------------
  699.  *      SendInitiate
  700.  *
  701.  *      Broadcasts WM_DDE_INITIATE message for the given reference string
  702.  *
  703.  *      Arguments:
  704.  *              szApp
  705.  *              szDoc
  706.  *
  707.  *      Returns:
  708.  *              Nothing
  709.  */
  710. void SendInitiate(szApp, szDoc)
  711. char *szApp;
  712. char *szDoc;
  713. {
  714.     ATOM atomApp, atomDoc;
  715.  
  716.     atomApp = *szApp == 0 ? NULL : GlobalAddAtom((LPSTR)szApp);
  717.     atomDoc = *szDoc == 0 ? NULL : GlobalAddAtom((LPSTR)szDoc);
  718.     iAck = FALSE;        /* no conversation is active */
  719.     fInInitiate = TRUE;
  720.     SendMessage((HWND)-1, WM_DDE_INITIATE, hwndDDE, MAKELONG(atomApp, atomDoc));
  721.     fInInitiate = FALSE;
  722.     if (atomApp != NULL)
  723.             GlobalDeleteAtom(atomApp);
  724.     if (atomDoc != NULL)
  725.             GlobalDeleteAtom(atomDoc);
  726.     if (!iAck)
  727.       MessageBox( GetFocus(), "Nobody wants to talk.", "Warning", MB_OK);
  728.  
  729. }
  730.  
  731.  
  732. /* -----------------------------------------------------
  733.  *      SendTerminate
  734.  *
  735.  *      Arguments:
  736.  *              icl
  737.  *
  738.  *      Returns:
  739.  *              Nothing.
  740.  */
  741. void SendTerminate(icl)
  742. int icl;
  743. {
  744. #ifdef BOGUS
  745.     PostClientMsg(icl, WM_DDE_UNADVISE, 0, 0);
  746.     if (!FGetAck(icl)) {
  747.             Error("Terminate aborted:  Unadvise failed");
  748.             return;
  749.     }
  750. #endif
  751.     PostClientMsg(icl, WM_DDE_TERMINATE, 0, 0);
  752.     RemoveLinks(icl);
  753.     RemovePl(hplcl, icl);
  754. }
  755.  
  756.  
  757. /* -----------------------------------------------------
  758.  *      SendRequest
  759.  *
  760.  *      Sends a WM_DDE_REQUEST message
  761.  *
  762.  *      Arguments:
  763.  *              icl
  764.  *              cf
  765.  *              szRef
  766.  *
  767.  *      Returns:
  768.  *              Nothing.
  769.  */
  770. void SendRequest(icl, cf, szRef)
  771. int icl;
  772. int cf;
  773. char *szRef;
  774. {
  775.    ATOM atom;
  776.  
  777.    atom = GlobalAddAtom((LPSTR)szRef);
  778.    PostClientMsg(icl, WM_DDE_REQUEST, atom, cf);
  779. }
  780.  
  781.  
  782. /* -----------------------------------------------------
  783.  *      SendAdvise
  784.  *
  785.  *      Sends WM_DDE_ADVISE message to establish hot link
  786.  *
  787.  *      Arguments:
  788.  *              icl
  789.  *              cf
  790.  *              szRef
  791.  *
  792.  *      Returns:
  793.  *              Nothing.
  794.  */
  795. void SendAdvise(icl, cf, szRef)
  796. int icl;
  797. int cf;
  798. char *szRef;
  799. {
  800.    ATOM atom;
  801.    HANDLE hDdeln;
  802.    DDELN far *lpddeln;
  803.    BOOL fSuccess;
  804.    DL dl;
  805.  
  806.    atom = GlobalAddAtom((LPSTR)szRef);
  807.    hDdeln = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (DWORD)sizeof(DDELN));
  808.    lpddeln = (DDELN far *)GlobalLock(hDdeln);
  809.    lpddeln->cf = cf;
  810.    lpddeln->fAckReq = FALSE;
  811.    lpddeln->fDeferUpd = FALSE;
  812.    GlobalUnlock(hDdeln);
  813.    PostClientMsg(icl, WM_DDE_ADVISE, atom, hDdeln);
  814.    if (!FGetAck(icl)) {
  815.       Error("Advise Failed");
  816.       GlobalFree(hDdeln);
  817.       /* return; */
  818.    }
  819.    else {
  820.      dl.icl = icl;
  821.      dl.atomRef = atom;
  822.      AddPl(hpldl, &dl);
  823.    }
  824. }
  825.  
  826.  
  827. /* -----------------------------------------------------
  828.  *      SendUnadvise
  829.  *
  830.  *      Breaks a link by sending an WM_DDE_UNADVISE.
  831.  *
  832.  *      Arguments:
  833.  *              icl
  834.  *              szRef
  835.  *
  836.  *      Returns:
  837.  *              Nothing.
  838.  */
  839. void SendUnadvise(icl, szRef)
  840. int icl;
  841. char *szRef;
  842. {
  843.    ATOM atom;
  844.    PLDL *ppldl;
  845.    int idl;
  846.  
  847.    if (*szRef == 0) {
  848.       PostClientMsg(icl, WM_DDE_UNADVISE, NULL, NULL);
  849.       if (!FGetAck(icl)) {
  850.          Error("Unadvise Failed");
  851.          return;
  852.       }
  853.       RemoveLinks(icl);
  854.       return;
  855.    }
  856.    atom = GlobalAddAtom((LPSTR)szRef);
  857.    ppldl = (PLDL *)LocalLock((HANDLE)hpldl);
  858.    for (idl = 0; idl < ppldl->idlMax; idl++) {
  859.       if (ppldl->rgdl[idl].fUsed &&
  860.           ppldl->rgdl[idl].atomRef == atom &&
  861.           ppldl->rgdl[idl].icl == icl) {
  862.          PostClientMsg(icl, WM_DDE_UNADVISE, atom, NULL);
  863.          if (!FGetAck(icl)) {
  864.             Error("Unadvise Failed");
  865.             break;
  866.          }
  867.          GlobalDeleteAtom(atom);
  868.          RemovePl(hpldl, idl);
  869.          break;
  870.       }
  871.    }
  872.    LocalUnlock((HANDLE)hpldl);
  873. }
  874.  
  875.  
  876. /* -----------------------------------------------------
  877.  *      SendExecute
  878.  *
  879.  *      Sends a WM_DDE_EXECUTE.
  880.  *
  881.  *      Arguments:
  882.  *              icl
  883.  *              szExec
  884.  *
  885.  *      Returns:
  886.  *              Nothing.
  887.  */
  888. void SendExecute(icl, szExec)
  889. int icl;
  890. char *szExec;
  891. {
  892.    int cch;
  893.    char far *lpsz;
  894.    HANDLE hDde;
  895.  
  896.    cch  = CchSzLen((char far *)szExec);
  897.    hDde = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (DWORD)cch+1);
  898.    lpsz = (char far *)GlobalLock(hDde);
  899.    bltbx((char far *)szExec, lpsz, cch+1);
  900.    GlobalUnlock(hDde);
  901.    PostClientMsg(icl, WM_DDE_EXECUTE, hDde, NULL);
  902.    if (!FGetAck(icl))
  903.            Error("Execute Failed");
  904.    GlobalFree(hDde);
  905. }
  906.  
  907. /* -----------------------------------------------------
  908.  *      SendPoke
  909.  *
  910.  *      Sends a WM_DDE_POKE
  911.  *
  912.  *      Arguments:
  913.  *              icl
  914.  *              szRef
  915.  *              szPoke
  916.  *
  917.  *      Returns:
  918.  *              Nothing.
  919.  */
  920. void SendPoke(icl, szRef, szPoke)
  921. int icl;
  922. char *szRef;
  923. char *szPoke;
  924. {
  925.    int cch;
  926.    DDEUP far *lpddeup;
  927.    ATOM atom;
  928.    HANDLE hDdeup;
  929.  
  930.    switch(iRadioButton) {
  931.  
  932.      case idradioText:
  933.           MessageBox( GetFocus(), "Text", "Sending", MB_OK);
  934.           break;
  935.  
  936.      case idradioCsv:
  937.           MessageBox( GetFocus(), "Csv" , "Sending", MB_OK);
  938.           break;
  939.  
  940.      case idradioFile:
  941.           MessageBox( GetFocus(), "File" , "Sending", MB_OK);
  942.           break;
  943.  
  944.      default:
  945.           MessageBox( GetFocus(), "Unknown" , NULL, MB_OK);
  946.           break;
  947.    }
  948.  
  949.    atom   = GlobalAddAtom((LPSTR)szRef);
  950.    cch    = CchSzLen((char far *)szPoke);
  951.    hDdeup = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (DWORD)sizeof(DDEUP)+cch);
  952.    lpddeup            = (DDEUP far *)GlobalLock(hDdeup);
  953.    lpddeup->cf        = (iRadioButton == idradioText) ? CF_TEXT : rgcf[icfCSV];
  954.    lpddeup->fAckReq   = FALSE;
  955.    lpddeup->fRelease  = TRUE;
  956.    bltbx((char far *)szPoke, lpddeup->rgb, cch+1);
  957.    GlobalUnlock(hDdeup);
  958.    PostClientMsg(icl, WM_DDE_POKE, atom, hDdeup);
  959.    if (!FGetAck(icl))
  960.            Error("Poke Failed");
  961. }
  962.  
  963. /* -----------------------------------------------------
  964.  *      BenchPoke
  965.  *
  966.  *      Sends a whole bunch of WM_DDE_POKEs
  967.  *
  968.  *      Arguments:
  969.  *              icl
  970.  *              szRef
  971.  *              szPoke
  972.  *
  973.  *      Returns:
  974.  *              Nothing.
  975.  */
  976. void BenchPoke(icl, szRef, szPoke)
  977. int icl;
  978. char *szRef;
  979. char *szPoke;
  980. {
  981.   int i;
  982.   int cch;
  983.   DDEUP far *lpddeup;
  984.   ATOM atom;
  985.   HANDLE hDdeup;
  986.  
  987.   Error("Start");
  988.   for (i=0; i<10000; i++)
  989.           {
  990.           PostClientMsg(icl, WM_DDE_TEST, NULL, NULL);
  991.           if (!FGetAck(icl))
  992.                   Error("No Ack Received");
  993.           }
  994.   Error("Stop");
  995. }
  996.  
  997.  
  998. /* ----------------------------------------------------- */
  999. int Waste(hwnd, wm, wParam, lParam)
  1000. HWND hwnd;
  1001. int wm;
  1002. int wParam;
  1003. long lParam;
  1004. {
  1005.         return(TRUE);
  1006. }
  1007.  
  1008.  
  1009. /* ----------------------------------------------------- */
  1010. void BenchCall()
  1011. {
  1012.   long l;
  1013.  
  1014.   Error("Start");
  1015.   for (l=0; l<1000000; l++)
  1016.           if (!Waste(1234, WM_DDE_TEST, 5678, 0L))
  1017.                   Error("No Ack Received");
  1018.   Error("Stop");
  1019. }
  1020.  
  1021.  
  1022. /* -----------------------------------------------------
  1023.  *      FGetAck
  1024.  *
  1025.  *      Waits for an ACK message to be returned
  1026.  *
  1027.  *      Arguments:
  1028.  *              icl             channel to receive ACK from
  1029.  *
  1030.  *      Returns:
  1031.  *              TRUE if affirmative ACK received within a fairly long
  1032.  *              time period
  1033.  *
  1034.  *      Note:
  1035.  *              This method is not recommended for large applications.
  1036.  */
  1037. BOOL FGetAck(icl)
  1038. HWND icl;
  1039. {
  1040.     MSG msg;
  1041.     int tid;
  1042.     HWND hwndInt, hwndExt;
  1043.     BOOL fAck;
  1044. #define msAckWait 60000 /* one minute */
  1045.  
  1046.     hwndExt = (*hplcl)->rgcl[icl].hwndExt;
  1047.     hwndInt = (*hplcl)->rgcl[icl].hwndInt;
  1048. #ifdef TIMER
  1049.     tid = SetTimer(NULL, 0, msAckWait, NULL);
  1050. #endif
  1051.     fAck = FALSE;
  1052.     for (;;) {
  1053.        GetMessage((MSG far *)&msg, NULL, 0, 0);
  1054.        if (msg.message == WM_DDE_ACK && msg.wParam == hwndExt)
  1055.           {
  1056.           if (LOWORD(msg.lParam) & 0x8000)
  1057.                   fAck = TRUE;
  1058.           if (HIWORD(msg.lParam)>= 0xc000)
  1059.                   GlobalDeleteAtom(HIWORD(msg.lParam));
  1060.           break;
  1061.           }
  1062.        TranslateMessage((MSG far *)&msg);
  1063.        DispatchMessage((MSG far *)&msg);
  1064. #ifdef TIMER
  1065.        if (PeekMessage((MSG far *)&msg, NULL,
  1066.                            WM_TIMER, WM_TIMER, PM_REMOVE) &&
  1067.                        msg.wParam == tid)
  1068.                break;
  1069. #endif
  1070.        WaitMessage();
  1071.     }
  1072. #ifdef TIMER
  1073.     KillTimer(NULL, tid);
  1074. #endif
  1075.     return(fAck);
  1076. }
  1077.  
  1078.  
  1079.  
  1080.  
  1081. /* -----------------------------------------------------
  1082.  * P A S T E  L I N K 
  1083.  *
  1084.  *  Get the paste link string from the clipboard and display it.
  1085.  *
  1086. */
  1087.  
  1088. void PasteLink ()
  1089. {
  1090.    int  isp;
  1091.    char far *lpch;
  1092.    char far *lpchT;
  1093.    RECT rect;
  1094.    HDC  hdc;
  1095.    HANDLE hClipboard;
  1096.  
  1097.    if (!OpenClipboard(hwndDDE))
  1098.        {
  1099.        Error("Cannot open clipboard");
  1100.        return;
  1101.        }
  1102.  
  1103.    if ((hClipboard = GetClipboardData(cfLink)) == NULL)
  1104.        {
  1105.        Error("Cannot render clipboard in Link format");
  1106.        }
  1107.    else
  1108.        {
  1109.        hdc = GetDC(hwndDDE);
  1110.        lpch = GlobalLock(hClipboard);
  1111.        GetClientRect(hwndDDE, (LPRECT)&rect);
  1112.        hbrBack = SelectObject(hdc, hbrBack);
  1113.        PatBlt(hdc, rect.left, rect.top, rect.right - rect.left,
  1114.                 rect.bottom - rect.top, PATCOPY);
  1115.        SelectObject(hdc, hbrBack);
  1116.        for (isp=0, lpchT = lpch; isp < 2; lpchT++)
  1117.                if (!*lpchT)
  1118.                        {
  1119.                        *lpchT = ' ';
  1120.                        isp++;
  1121.                        }
  1122.        DrawText(hdc, lpch, CchSzLen(lpch), (LPRECT)&rect,
  1123.                DT_LEFT|DT_EXPANDTABS);
  1124.        ReleaseDC(hwndDDE, hdc);
  1125.        GlobalUnlock(hClipboard);
  1126.        }
  1127.  
  1128.    CloseClipboard();
  1129. }
  1130.  
  1131.  
  1132. /* -----------------------------------------------------
  1133.  *      DoDialog
  1134.  *
  1135.  *      Brings up a dialog.
  1136.  *
  1137.  *      Arguments:
  1138.  *              idd             dialog index to bring up
  1139.  *              lpfn            dialog proc to use
  1140.  *
  1141.  *      Returns:
  1142.  *              Dialog return code
  1143.  */
  1144. int FDoDialog(idd, lpfn)
  1145. int idd;
  1146. FARPROC lpfn;
  1147. {
  1148.    int w;
  1149.  
  1150.    lpfn = MakeProcInstance(lpfn, hinstDDE);
  1151.    w = DialogBox(hinstDDE, MAKEINTRESOURCE(idd), hwndDDE, lpfn);
  1152.    FreeProcInstance(lpfn);
  1153.    return(w);
  1154. }
  1155.  
  1156.  
  1157. /* ----------------------------------------------------
  1158.  *      ClipFmtBox
  1159.  *
  1160.  *      Initializes clipboard format dialog list box.
  1161.  *
  1162.  *      Arguments:
  1163.  *              hdlg
  1164.  *              idlbox
  1165.  *
  1166.  *      Returns:
  1167.  *              nothing.
  1168.  */
  1169. void ClipFmtBox(hdlg, idlbox)
  1170. HWND hdlg;
  1171. int idlbox;
  1172. {
  1173.     HWND hctl;
  1174.     int icf;
  1175.     int cf;
  1176.     char sz[256];
  1177.  
  1178.     hctl = GetDlgItem(hdlg, idlbox);
  1179.     for (icf = 0; icf < icfMax; icf++) {
  1180.         switch (cf = rgcf[icf]) {
  1181.         case CF_TEXT:
  1182.                 bltbx((LPSTR)"CF_TEXT", (LPSTR)sz, 8);
  1183.                 break;
  1184.         case CF_BITMAP:
  1185.                 bltbx((LPSTR)"CF_BITMAP", (LPSTR)sz, 10);
  1186.                 break;
  1187.         case CF_METAFILEPICT:
  1188.                 bltbx((LPSTR)"CF_METAFILEPICT", (LPSTR)sz, 12);
  1189.                 break;
  1190.         case CF_SYLK:
  1191.                 bltbx((LPSTR)"CF_SYLK", (LPSTR)sz, 8);
  1192.                 break;
  1193.         case CF_DIF:
  1194.                 bltbx((LPSTR)"CF_DIF", (LPSTR)sz, 7);
  1195.                 break;
  1196.         default:
  1197.                 sz[GetClipboardFormatName(cf, (LPSTR)sz, sizeof(sz))] = 0;
  1198.                 break;
  1199.         }
  1200.         SendMessage(hctl, LB_ADDSTRING, 0, (DWORD)(LPSTR)sz);
  1201.     }
  1202. }
  1203.  
  1204.  
  1205. /* ----------------------------------------------------
  1206.  *      ChnlBox
  1207.  *
  1208.  *      Initializes channel dialog list box.
  1209.  *
  1210.  *      Arguments:
  1211.  *              hdlg
  1212.  *              idlbox
  1213.  *
  1214.  *      Returns:
  1215.  *              nothing.
  1216.  */
  1217. void ChnlBox(hdlg, idlbox)
  1218. HWND hdlg;
  1219. int idlbox;
  1220. {
  1221.     HWND hctl;
  1222.     PLCL *pplcl;
  1223.     int icl;
  1224.     HWND hwndExt;
  1225.     char sz[256];
  1226.  
  1227.     hctl = GetDlgItem(hdlg, idlbox);
  1228.     pplcl = (PLCL *)LocalLock((HANDLE)hplcl);
  1229.     for (icl = 0; icl < pplcl->iclMax; icl++) {
  1230.         if (!pplcl->rgcl[icl].fUsed)
  1231.                 continue;
  1232.         hwndExt = pplcl->rgcl[icl].hwndExt;
  1233.         GetWindowText(hwndExt, (LPSTR)sz, sizeof(sz));
  1234.         SendMessage(hctl, LB_ADDSTRING, 0, (DWORD)(LPSTR)sz);
  1235.     }
  1236.     LocalUnlock((HANDLE)hplcl);
  1237. }
  1238.  
  1239.  
  1240. /* ----------------------------------------------------
  1241.  *      IclListBox
  1242.  *
  1243.  *      Given a listbox, returns the icl for the channel selected in that
  1244.  *      listobx.
  1245.  *
  1246.  *      Arguments:
  1247.  *              hdlg            dialog handle
  1248.  *              idlbox          listbox item index.
  1249.  *
  1250.  *      Returns:
  1251.  *              channel index
  1252.  */
  1253. int IclListBox(hdlg, idlbox)
  1254. HWND hdlg;
  1255. int idlbox;
  1256. {
  1257.     int il, icl;
  1258.     PLCL *pplcl;
  1259.  
  1260.     if ((il = SendMessage(GetDlgItem(hdlg, idlbox), LB_GETCURSEL, 0, 0L)) == -1)
  1261.             return(-1);
  1262.     pplcl = (PLCL *)LocalLock((HANDLE)hplcl);
  1263.     for (icl = 0; icl < pplcl->iclMax; icl++) {
  1264.             if (pplcl->rgcl[icl].fUsed && il-- == 0)
  1265.                     goto Return;
  1266.     }
  1267.     icl = -1;
  1268. Return:
  1269.     LocalUnlock((HANDLE)hplcl);
  1270.     return(icl);
  1271. }
  1272.  
  1273. /* ---------------------------------------------------- */
  1274.  
  1275. void PostClientMsg(icl, wm, atom, cf)
  1276. int icl;
  1277. int wm;
  1278. ATOM atom;
  1279. int cf;
  1280. {
  1281.     HWND hwndExt;
  1282.     PLCL *pplcl;
  1283.  
  1284.     pplcl = (PLCL *)LocalLock((HANDLE)hplcl);
  1285.     hwndExt = pplcl->rgcl[icl].hwndExt;
  1286.     PostMessage(hwndExt, wm,
  1287.             (WORD)pplcl->rgcl[icl].hwndInt,
  1288.             MAKELONG(cf, atom));
  1289.     LocalUnlock((HANDLE)hplcl);
  1290. }
  1291.  
  1292.  
  1293. int cxScrollLast;
  1294. int cyScrollLast;
  1295.  
  1296. /* ---------------------------------------------------- */
  1297. FShowMetaFilePict( hdc, prc, hmfp, cxScroll, cyScroll )
  1298. HDC      hdc;
  1299. register PRECT  prc;
  1300. HANDLE   hmfp;
  1301. int      cxScroll, cyScroll;
  1302. {       /* Display a metafile picture in the passed rectangle.
  1303.            { cxScroll, cyScroll } is the origin within the picture at which
  1304.                         to start displaying.
  1305.            Set cxScrollLast, cyScrollLast if they have not been set already */
  1306.    HDC hMemDC;
  1307.    HBITMAP hbm;
  1308.    LPMETAFILEPICT lpmfp;
  1309.    METAFILEPICT mfp;
  1310.    int mmT;
  1311.    POINT pt, ptT;
  1312.    int level;
  1313.    int cxRect = prc->right - prc->left;
  1314.    int cyRect = prc->bottom - prc->top;
  1315.    int cxBitmap;
  1316.    int cyBitmap;
  1317.    int f=FALSE;
  1318.  
  1319.    if ((lpmfp=(LPMETAFILEPICT)GlobalLock( hmfp )) != NULL)
  1320.       {
  1321.       int mm;
  1322.       METAFILEPICT mfp;
  1323.  
  1324.       mfp = *lpmfp;
  1325.       GlobalUnlock( hmfp );
  1326.  
  1327.       if ((level = SaveDC( hdc )) != 0)
  1328.          {
  1329.          /* Compute size of picture to be displayed */
  1330.  
  1331.          switch (mfp.mm)
  1332.                  {
  1333.          case MM_ISOTROPIC:
  1334.                  goto NoScroll;
  1335.          case MM_ANISOTROPIC:
  1336.                  if (mfp.xExt > 0 && mfp.yExt > 0)
  1337.                          {
  1338.                          /* suggested a size */
  1339.                          mm = MM_HIMETRIC;
  1340.                          goto GetSize;
  1341.                          }
  1342. NoScroll:
  1343.                  /* no suggested sizes, use the window size */
  1344.                  cyScrollLast = 0;   /* Not scrollable; resizes into avail. rect */
  1345.                  cxScrollLast = 0;
  1346.                  cxBitmap = prc->right - prc->left;
  1347.                  cyBitmap = prc->bottom - prc->top;
  1348.                  break;
  1349.  
  1350.          default:
  1351.                  mm = mfp.mm;
  1352. GetSize:
  1353.                  mmT = SetMapMode(hdc, mm);
  1354.                  *((long *)&ptT) = SetWindowOrg(hdc, 0, 0);
  1355.                  pt.x = mfp.xExt;
  1356.                  pt.y = mfp.yExt;
  1357.                  LPtoDP(hdc, (LPPOINT)&pt, 1);
  1358.                  cxBitmap = pt.x;
  1359.                  cyBitmap = (mm == MM_TEXT) ? pt.y : -pt.y;
  1360.                  SetMapMode(hdc, mmT);
  1361.                  SetWindowOrg(hdc, ptT.x, ptT.y);
  1362.  
  1363. CheckScroll:
  1364.                  if (cxScrollLast == -1)
  1365.                          {
  1366.                          cxScrollLast = cxBitmap - (prc->right - prc->left);
  1367.                          if ( cxScrollLast < 0)
  1368.                                  cxScrollLast = 0;
  1369.                          }
  1370.                  if (cyScrollLast == -1)
  1371.                          {
  1372.                          cyScrollLast = cyBitmap - (prc->bottom - prc->top);
  1373.                          if ( cyScrollLast < 0)
  1374.                                  cyScrollLast = 0;
  1375.                          }
  1376.                  break;
  1377.                  }
  1378.  
  1379.          /* We make the "viewport" to be an area the same size as the */
  1380.          /* clipboard object, and set the origin and clip region so as */
  1381.          /* to show the area we want. Note that the viewport may well be */
  1382.          /* bigger than the window. */
  1383.          IntersectClipRect( hdc, prc->left, prc->top,
  1384.                                  prc->right, prc->bottom );
  1385.          SetMapMode( hdc, mfp.mm );
  1386.  
  1387.          SetViewportOrg( hdc, prc->left - cxScroll, prc->top - cyScroll );
  1388.          switch (mfp.mm)
  1389.                  {
  1390.          case MM_ISOTROPIC:
  1391.                  if (mfp.xExt && mfp.yExt)
  1392.                          /* So we get the correct shape rectangle when
  1393.                          SetViewportExt gets called */
  1394.                          SetWindowExt( hdc, mfp.xExt, mfp.yExt );
  1395.                  break;
  1396.  
  1397.          case MM_ANISOTROPIC:
  1398.                  SetWindowExt(hdc, cxBitmap, cyBitmap);
  1399.                  SetViewportExt( hdc, cxBitmap, cyBitmap );
  1400.                  break;
  1401.                  }
  1402.  
  1403.          /* Since we may have scrolled, force brushes to align */
  1404.          SetBrushOrg( hdc, cxScroll - prc->left, cyScroll - prc->top );
  1405.          f = PlayMetaFile( hdc, mfp.hMF );
  1406.  
  1407. NoDisplay:
  1408.          RestoreDC( hdc, level );
  1409.          }
  1410.       }
  1411.  
  1412. return f;
  1413.  
  1414. }
  1415.  
  1416. /* ------------------------------------------------------
  1417.  *      DdeWndProc
  1418.  *
  1419.  *      Main window proc for the DDE application.
  1420.  *
  1421.  *      Arguments:
  1422.  *              hwnd            window receiving the message
  1423.  *              wm              the message
  1424.  *              wParam, lParam  additional info for the message
  1425.  *
  1426.  *      Returns:
  1427.  *              Depends on the message.
  1428.  */
  1429. long far pascal DdeWndProc(hwnd, wm, wParam, lParam)
  1430. HWND hwnd;
  1431. unsigned wm;
  1432. int wParam;
  1433. long lParam;
  1434. {
  1435.    int icl;
  1436.    PLCL *pplcl;
  1437.    char sz[256];
  1438.    char *pch;
  1439.    RECT rect;
  1440.    HDC hdc;
  1441.    DDEUP far *lpddeup;
  1442.    CL cl;
  1443.    HBITMAP hbmp;
  1444.    HDC hdcMem;
  1445.    BITMAP bmp;
  1446.    METAFILEPICT far *lpmfp;
  1447.    HANDLE hMF;
  1448.    BOOL fRelease;
  1449.  
  1450.    switch (wm) {
  1451.  
  1452.            case WM_DESTROY:
  1453.                    PostQuitMessage(0);
  1454.                    break;
  1455.  
  1456.            case WM_COMMAND:
  1457.  
  1458.                    switch (wParam) {
  1459.  
  1460.                    case idmInitiate:
  1461.                            if (FDoDialog(iddInitiate, InitiateDlg))
  1462.                                    SendInitiate(szApp, szDoc);
  1463.                            return(0L);
  1464.  
  1465.                    case idmTerminate:
  1466.                            if (FDoDialog(iddTerminate, TermDlg))
  1467.                                    SendTerminate(iclCur);
  1468.                            return(0L);
  1469.  
  1470.                    case idmRequest:
  1471.                            if (FDoDialog(iddRequest, RequestDlg))
  1472.                                    SendRequest(iclCur, cfCur, szRef);
  1473.                            return(0L);
  1474.  
  1475.                    case idmAdvise:
  1476.                            if (FDoDialog(iddAdvise, RequestDlg))
  1477.                                    SendAdvise(iclCur, cfCur, szRef);
  1478.                            return(0L);
  1479.  
  1480.                    case idmUnadvise:
  1481.                            if (FDoDialog(iddUnadvise, UnadviseDlg))
  1482.                                    SendUnadvise(iclCur, szRef);
  1483.                            return(0L);
  1484.  
  1485.                    case idmPoke:
  1486.                            if (FDoDialog(iddPoke, PokeDlg))
  1487.                                    SendPoke(iclCur, szRef, szData);
  1488.                            return(0L);
  1489.  
  1490.                    case idmExecute:
  1491.                            if (FDoDialog(iddExecute, ExecuteDlg))
  1492.                                    SendExecute(iclCur, szRef);
  1493.                            return(0L);
  1494.  
  1495.                    case idmBench:
  1496.                            if (FDoDialog(iddPoke, PokeDlg))
  1497.                                    BenchPoke(iclCur, szRef, szData);
  1498.                            return(0L);
  1499.  
  1500.                    case idmCBench:
  1501.                            BenchCall();
  1502.                            return(0L);
  1503.  
  1504.                    case idmPasteLink:
  1505.                            PasteLink();
  1506.                            return(0L);
  1507.  
  1508.                    default:
  1509.                            break;
  1510.  
  1511.                    }
  1512.                    break;
  1513.  
  1514.            case WM_DDE_TERMINATE:
  1515.                    pplcl = (PLCL *)LocalLock((HANDLE)hplcl);
  1516.                    for (icl = 0; icl < pplcl->iclMax; icl++) {
  1517.                            if (!pplcl->rgcl[icl].fUsed ||
  1518.                                pplcl->rgcl[icl].hwndExt != wParam)
  1519.                                    continue;
  1520.                            LocalUnlock((HANDLE)hplcl);
  1521.                            SendTerminate(icl);
  1522.                            return(0L);
  1523.                            }
  1524.                    LocalUnlock((HANDLE)hplcl);
  1525.                    return(0L);
  1526.  
  1527.            case WM_DDE_ACK:
  1528.                    if (fInInitiate) {
  1529.                            cl.hwndInt = hwnd;
  1530.                            cl.hwndExt = (HWND)wParam;
  1531.                            cl.fClient = TRUE;
  1532.                            AddPl(hplcl, &cl);
  1533.                            GlobalDeleteAtom(LOWORD(lParam));
  1534.                            iAck = TRUE;
  1535.                    } else {
  1536.                            if (LOWORD(lParam) & 0x8000)
  1537.                                    Error("Got ACK");
  1538.                            else
  1539.                                    Error("Got NACK");
  1540.                    }
  1541.                    GlobalDeleteAtom(HIWORD(lParam));
  1542.                    return(0L);
  1543.  
  1544.            case WM_DDE_DATA:
  1545.                    GetClientRect(hwndDDE, (LPRECT)&rect);
  1546.                    hdc = GetDC(hwndDDE);
  1547.                    hbrBack = SelectObject(hdc, hbrBack);
  1548.                    PatBlt(hdc, rect.left, rect.top,
  1549.                                    rect.right - rect.left,
  1550.                                    rect.bottom - rect.top,
  1551.                                    PATCOPY);
  1552.                    SelectObject(hdc, hbrBack);
  1553.                    lpddeup = (DDEUP far *)GlobalLock(LOWORD(lParam));
  1554.                    if (lpddeup->fAckReq)
  1555.                            PostMessage(wParam, WM_DDE_ACK,
  1556.                                    hwnd, MAKELONG(0x8000, HIWORD(lParam)));
  1557.                    else
  1558.                            GlobalDeleteAtom(HIWORD(lParam));
  1559.                    switch (lpddeup->cf)
  1560.                            {
  1561.                    default:
  1562.                            if (lpddeup->cf == rgcf[icfBitPrinter])
  1563.                                    goto GotBitmap;
  1564.                            if (lpddeup->cf == rgcf[icfMetaPrinter])
  1565.                                    goto GotMetafile;
  1566.                            if (lpddeup->cf != rgcf[icfRTF] &&
  1567.                                    lpddeup->cf != rgcf[icfCSV])
  1568.                                    break;
  1569.                            /* else fall through */
  1570.                    case CF_SYLK:
  1571.                    case CF_DIF:
  1572.                    case CF_TEXT:
  1573.                            DrawText(hdc, lpddeup->rgb,
  1574.                                            CchSzLen(lpddeup->rgb),
  1575.                                            (LPRECT)&rect,
  1576.                                            DT_LEFT|DT_EXPANDTABS);
  1577.                            break;
  1578.                    case CF_BITMAP:
  1579. GotBitmap:
  1580.                            hdcMem = CreateCompatibleDC(hdc);
  1581.                            hbmp = *(HBITMAP far *)&lpddeup->rgb[0];
  1582.                            GetObject(hbmp, sizeof(BITMAP), (BYTE far *)&bmp);
  1583.                            hbmp = SelectObject(hdcMem, hbmp);
  1584.                            BitBlt(hdc, 0, 0, bmp.bmWidth, bmp.bmHeight,
  1585.                                            hdcMem, 0, 0, SRCCOPY);
  1586.                            hbmp = SelectObject(hdcMem, hbmp);
  1587.                            DeleteDC(hdcMem);
  1588.                            if (lpddeup->fRelease)
  1589.                                    DeleteObject(hbmp);
  1590.                            break;
  1591.                    case CF_METAFILEPICT:
  1592. GotMetafile:
  1593.                            GetClientRect(hwndDDE, (LPRECT)&rect);
  1594.                            FShowMetaFilePict(hdc, &rect, 
  1595.                                      *((HANDLE far *)&lpddeup->rgb[0]),
  1596.                                              0, 0);
  1597.                            if (lpddeup->fRelease)
  1598.                                    DeleteMetaFile(*((HANDLE far *)&lpddeup->rgb[0]));
  1599.                            break;
  1600.                    }
  1601.                    ReleaseDC(hwndDDE, hdc);
  1602.                    fRelease = lpddeup->fRelease;
  1603.                    GlobalUnlock(LOWORD(lParam));
  1604.                    if (fRelease)
  1605.                            GlobalFree(LOWORD(lParam));
  1606.                    return(0L);
  1607.  
  1608.            default:
  1609.                    break;
  1610.  
  1611.    }
  1612.    return(DefWindowProc(hwnd, wm, wParam, lParam));
  1613. }
  1614.  
  1615.  
  1616.