home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK10 / MFC / SRC / OLEUI2.CP$ / oleui2
Encoding:
Text File  |  1992-03-19  |  15.5 KB  |  612 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library. 
  2. // Copyright (C) 1992 Microsoft Corporation 
  3. // All rights reserved. 
  4. //  
  5. // This source code is only intended as a supplement to the 
  6. // Microsoft Foundation Classes Reference and Microsoft 
  7. // QuickHelp documentation provided with the library. 
  8. // See these sources for detailed information regarding the 
  9. // Microsoft Foundation Classes product. 
  10.  
  11. #include "afxole.h"
  12. #pragma hdrstop
  13.  
  14. #include "afxoleUI.h"       // user interface parts
  15. #include "oleptr_.h"
  16.  
  17. #include "shellapi.h"
  18. #include "afxdlgs.h"        // for Change link dialog
  19.  
  20. #ifdef AFX_OLE_SEG
  21. #pragma code_seg(AFX_OLE_SEG)
  22. #endif
  23.  
  24. #ifdef _DEBUG
  25. #undef THIS_FILE
  26. static char BASED_CODE THIS_FILE[] = __FILE__;
  27. #endif
  28.  
  29. /////////////////////////////////////////////////////////////////////////////
  30. // User interface for COleClientItem (with Links)
  31.  
  32. // forward references
  33. static void FormatLinkInfo(COleClientItem* pItem, char* szInfoBuffer,
  34.         char* szClassNameBuffer);
  35.  
  36. /////////////////////////////////////////////////////////////////////////////
  37. // Links dialog
  38.  
  39. class COleLinksDlg : public CModalDialog
  40. {
  41. public:
  42.     COleClientDoc*  m_pDoc;
  43.     COleClientItem* m_pSingleSelection; // NULL if 0 or >1 items selected
  44.     int             m_iSingleSelection; // listbox index (if above is not null)
  45.  
  46.     UINT    m_iVerb1;
  47.     UINT    m_iVerb2;
  48.  
  49.     // could be static members if desired
  50.     CString strEditVerb;
  51.     CString strActivateVerb;
  52.  
  53.     COleLinksDlg(COleClientDoc* pDoc)
  54.         : CModalDialog(AFX_IDD_LINKS)
  55.     {
  56.         m_pDoc = pDoc;
  57.         m_pSingleSelection = NULL;
  58.         VERIFY(strEditVerb.LoadString(AFX_IDS_EDIT_VERB));
  59.         VERIFY(strActivateVerb.LoadString(AFX_IDS_ACTIVATE_VERB));
  60.     }
  61.  
  62. protected:
  63.     BOOL OnInitDialog();
  64.     void SetVerbButtons(COleClientItem* pSel);
  65.     void DoVerb(UINT iVerb);
  66.  
  67.     // message map notifications
  68.     afx_msg void OnSelectionChange();
  69.  
  70.     afx_msg void OnVerb1();
  71.     afx_msg void OnVerb2();
  72.     afx_msg void OnAuto();
  73.     afx_msg void OnManual();
  74.     afx_msg void OnUpdate();
  75.     afx_msg void OnFreeze();
  76.     afx_msg void OnChange();
  77.  
  78.     DECLARE_MESSAGE_MAP()
  79. };
  80.  
  81.  
  82. BEGIN_MESSAGE_MAP(COleLinksDlg, CModalDialog)
  83.     // selection change
  84.     ON_LBN_SELCHANGE(AFX_IDC_LISTBOX, OnSelectionChange)
  85.  
  86.     // control notifications
  87.     ON_COMMAND(AFX_IDC_VERB1, OnVerb1)
  88.     ON_COMMAND(AFX_IDC_VERB2, OnVerb2)
  89.     ON_COMMAND(AFX_IDC_AUTO, OnAuto)
  90.     ON_COMMAND(AFX_IDC_MANUAL, OnManual)
  91.     ON_COMMAND(AFX_IDC_UPDATE, OnUpdate)
  92.     ON_COMMAND(AFX_IDC_FREEZE, OnFreeze)
  93.     ON_COMMAND(AFX_IDC_CHANGE, OnChange)
  94. END_MESSAGE_MAP()
  95.  
  96. /////////////////////////////////////////////////////////////////////////////
  97. // Initialize - fill in the information
  98.  
  99. BOOL COleLinksDlg::OnInitDialog()
  100. {
  101.     CListBox* pList = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
  102.     int cLinks = 0;
  103.  
  104.     // fill with links attached to this object
  105.     pList->ResetContent();
  106.  
  107.     int tabStops[3];
  108.     tabStops[0] = 20; // 20 50
  109.     tabStops[1] = 80; // 60 110
  110.     tabStops[2] = 120; // 85 200
  111.     pList->SetTabStops(3, tabStops);
  112.  
  113.     // enumerate over the client document - enumerate OLEOBJECTs
  114.     BOOL bSelected;
  115.     POSITION pos = m_pDoc->GetStartPosition();
  116.     COleClientItem* pItem;
  117.  
  118.     while ((pItem = m_pDoc->GetNextItem(pos, &bSelected)) != NULL)
  119.     {
  120.         if (pItem->GetType() == OT_LINK)
  121.         {
  122.             // add it to the listbox
  123.             int iItem;
  124.             char szInfo[OLE_MAXNAMESIZE * 2];       // assume this is enough
  125.  
  126.             FormatLinkInfo(pItem, szInfo, NULL);
  127.             if ((iItem = pList->AddString(szInfo)) == -1)
  128.             {
  129.                 TRACE("Warning: error filling listbox\n");
  130.                 EndDialog(IDCANCEL);
  131.                 return TRUE;
  132.             }
  133.             
  134.             pList->SetItemData(iItem, GetDWordFromPtr(pItem));
  135.             if (bSelected)
  136.                 pList->SetSel(iItem);
  137.             cLinks++;
  138.         }
  139.     }
  140.  
  141.     if (cLinks == 0)
  142.     {
  143.         TRACE("Warning: no links in this document\n");
  144.         EndDialog(IDCANCEL);    // no links after all
  145.         return TRUE;
  146.     }
  147.  
  148.     OnSelectionChange();        // enables buttons etc
  149.     return TRUE;
  150. }
  151.  
  152. struct LinkOptionsInfo
  153. {
  154.     int             nIDString;                  // IDS_ value to LoadString
  155.     int             nIDCheckButton;             // IDC_ for button to check
  156.     BOOL            bCanChangeLink;             // if can change or freeze
  157. };
  158.  
  159. static void GetLinkUpdateInfo(COleClientItem* pItem, LinkOptionsInfo* pInfo)
  160. {
  161.     // sensible defaults
  162.     pInfo->nIDString = AFX_IDS_FROZEN;
  163.     pInfo->nIDCheckButton = -1;
  164.     pInfo->bCanChangeLink = FALSE;
  165.  
  166.     if (pItem->GetType() != OT_LINK)
  167.         return;     // assume static
  168.  
  169.     switch (pItem->GetLinkUpdateOptions())
  170.     {
  171.     case oleupdate_always:
  172.         pInfo->nIDString = AFX_IDS_AUTO;
  173.         pInfo->nIDCheckButton = AFX_IDC_AUTO;
  174.         pInfo->bCanChangeLink = TRUE;
  175.         break;
  176.  
  177.     case oleupdate_oncall:
  178.         pInfo->nIDString = AFX_IDS_MANUAL;
  179.         pInfo->nIDCheckButton = AFX_IDC_MANUAL;
  180.         pInfo->bCanChangeLink = TRUE;
  181.         break;
  182.  
  183.     default:
  184.         break;      // default already setup (static)
  185.     }
  186. }
  187.  
  188.  
  189. static void FormatLinkInfo(COleClientItem* pItem, char* szInfoBuffer,
  190.         char* szClassNameBuffer)
  191. {
  192.     struct LinkOptionsInfo linkInfo;
  193.     CString strLinkType;
  194.  
  195.     GetLinkUpdateInfo(pItem, &linkInfo);
  196.     VERIFY(strLinkType.LoadString(linkInfo.nIDString));
  197.  
  198.     HANDLE hData = pItem->GetLinkFormatData();
  199.     ASSERT(hData != NULL);
  200.     LPCSTR lpszData = (LPCSTR)::GlobalLock(hData); // actually 3 strings
  201.     ASSERT(lpszData != NULL);
  202.  
  203.     if (szClassNameBuffer != NULL)
  204.         _fstrcpy(szClassNameBuffer, lpszData);
  205.  
  206.     if (szInfoBuffer != NULL)
  207.     {
  208.         // first server class name (use localized name if registered)
  209.         LONG    lSize = OLE_MAXNAMESIZE;
  210.         // get real language class of object in szClass for menu
  211.         if (::RegQueryValue(HKEY_CLASSES_ROOT, lpszData, szInfoBuffer,
  212.             &lSize) != ERROR_SUCCESS)
  213.         {
  214.             // no localized class name, use unlocalized name
  215.             _fstrcpy(szInfoBuffer, lpszData);
  216.         }
  217.         _fstrcat(szInfoBuffer, "\t");
  218.  
  219.         // document and item names
  220.         lpszData += _fstrlen(lpszData) + 1;
  221.  
  222.         // strip pathname and drive letter
  223.         LPCSTR lpszTemp = lpszData;
  224.         while (*lpszTemp)
  225.         {
  226.             if (*lpszTemp == '\\' || *lpszTemp == ':')
  227.                 lpszData = lpszTemp + 1;
  228.             lpszTemp = AnsiNext(lpszTemp);
  229.         }
  230.  
  231.         // Append the file name
  232.         _fstrcat(szInfoBuffer, lpszData);
  233.         _fstrcat(szInfoBuffer, "\t");
  234.  
  235.         // Append the item name
  236.         lpszData += _fstrlen(lpszData) + 1;
  237.         _fstrcat(szInfoBuffer, lpszData);
  238.         _fstrcat(szInfoBuffer, "\t");
  239.  
  240.         /* Append the type of link, and write it out */
  241.         _fstrcat(szInfoBuffer, strLinkType);
  242.     }
  243.  
  244.     ::GlobalUnlock(hData);
  245. }
  246.  
  247. // update button states depending on current selection
  248. void COleLinksDlg::OnSelectionChange()
  249. {
  250.     CListBox* pList = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
  251.     int nSelectedLinks = 0;
  252.     int nIDCheck = -1;
  253.     BOOL bCanChangeLink = FALSE;
  254.  
  255.     m_pSingleSelection = NULL;
  256.  
  257.     ASSERT(AFX_IDC_MANUAL == AFX_IDC_AUTO + 1);
  258.     if (pList->GetSelCount() != 0)
  259.     {
  260.         int nTotal = pList->GetCount();
  261.         for (int iItem = 0; iItem < nTotal; iItem++)
  262.         {
  263.             if (pList->GetSel(iItem) <= 0)
  264.                 continue;       // not selected
  265.  
  266.             COleClientItem* pItem;
  267.             pItem = (COleClientItem*)GetPtrFromDWord(pList->GetItemData(iItem));
  268.             ASSERT(pItem != NULL);
  269.             struct LinkOptionsInfo linkInfo;
  270.  
  271.             GetLinkUpdateInfo(pItem, &linkInfo);
  272.  
  273.             if (nSelectedLinks++ == 0)
  274.             {
  275.                 // first link
  276.                 nIDCheck = linkInfo.nIDCheckButton;
  277.                 bCanChangeLink = linkInfo.bCanChangeLink;
  278.                 m_pSingleSelection = pItem;
  279.                 m_iSingleSelection = iItem;
  280.             }
  281.             else
  282.             {
  283.                 if (nIDCheck != linkInfo.nIDCheckButton)    // not the same
  284.                     nIDCheck = -1;
  285.  
  286.                 // if multiple links selected - don't allow anything complex
  287.                 if (!linkInfo.bCanChangeLink)
  288.                     bCanChangeLink = FALSE;
  289.                 m_pSingleSelection = NULL;
  290.             }
  291.         }
  292.     }
  293.  
  294.     //BLOCK: do pushbutton verb stuff
  295.     SetVerbButtons(m_pSingleSelection);
  296.  
  297.     // disable if all in selection can be changed
  298.     GetDlgItem(AFX_IDC_UPDATE)->EnableWindow(bCanChangeLink);
  299.     GetDlgItem(AFX_IDC_FREEZE)->EnableWindow(bCanChangeLink);
  300.  
  301.     // simple Change button - only one link at a time
  302.     GetDlgItem(AFX_IDC_CHANGE)->EnableWindow(
  303.         (m_pSingleSelection != NULL) && bCanChangeLink);
  304.  
  305.  
  306.     CheckRadioButton(AFX_IDC_AUTO, AFX_IDC_MANUAL, nIDCheck);
  307.     // disable if nothing selected
  308.     GetDlgItem(AFX_IDC_AUTO)->EnableWindow(nSelectedLinks > 0);
  309.     GetDlgItem(AFX_IDC_MANUAL)->EnableWindow(nSelectedLinks > 0);
  310. }
  311.  
  312. /////////////////////////////////////////////////////////////////////////////
  313. // Standard verb buttons
  314.  
  315. static void SmartChangeButton(CWnd* pButton, const char* pszText, BOOL bEnable)
  316. {
  317.     char szOldText[OLE_MAXNAMESIZE];
  318.  
  319.     // avoid flashing if changing to same text
  320.     pButton->GetWindowText(szOldText, sizeof(szOldText));
  321.     if (strcmp(szOldText, pszText) != 0)
  322.         pButton->SetWindowText(pszText);
  323.     pButton->EnableWindow(bEnable);
  324. }
  325.  
  326. void COleLinksDlg::SetVerbButtons(COleClientItem* pSel)
  327. {
  328.     // defaults for no selection
  329.     const char* pszVerb1 = strActivateVerb;
  330.     BOOL bEnable1 = FALSE;
  331.     const char* pszVerb2 = strEditVerb;
  332.     BOOL bEnable2 = FALSE;
  333.  
  334.     // registered verb names
  335.     char szRegVerb0[OLE_MAXNAMESIZE];
  336.     char szRegVerb1[OLE_MAXNAMESIZE];
  337.  
  338.     ASSERT(OLEVERB_PRIMARY == 0);
  339.     m_iVerb1 = m_iVerb2 = 0;    // usually primary verb
  340.  
  341.     if (pSel != NULL)
  342.     {
  343.         // look at verbs for current selection
  344.         char szClass[OLE_MAXNAMESIZE];
  345.         FormatLinkInfo(pSel, NULL, szClass);
  346.  
  347.         szRegVerb0[0] = szRegVerb1[0] = '\0';
  348.         int cVerbs = 0;
  349.         while (cVerbs < 2)
  350.         {
  351.             char    szBuffer[OLE_MAXNAMESIZE+40];
  352.             wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb\\%d",
  353.                      (LPCSTR)szClass, cVerbs);
  354.  
  355.             /* get verb name */
  356.             char* pszVerb = (cVerbs == 0) ? szRegVerb0 : szRegVerb1;
  357.             LONG lSize = OLE_MAXNAMESIZE;
  358.             if (::RegQueryValue(HKEY_CLASSES_ROOT, szBuffer,
  359.                pszVerb, &lSize) != 0)
  360.                 break; // finished counting verbs
  361.             cVerbs++;
  362.         }
  363.  
  364.         if (cVerbs == 0)
  365.         {
  366.             // no special verbs, enable generic edit
  367.             bEnable2 = TRUE;
  368.         }
  369.         else if (cVerbs == 1)
  370.         {
  371.             // 1 special verb, special case if 'edit'
  372.             if (_stricmp(szRegVerb0, strEditVerb) == 0)
  373.             {
  374.                 // edit goes on second button
  375.                 bEnable2 = TRUE;
  376.             }
  377.             else
  378.             {
  379.                 // other verb goes on top
  380.                 pszVerb1 = szRegVerb0;
  381.                 bEnable1 = TRUE;
  382.             }
  383.         }
  384.         else // 2 verbs
  385.         {
  386.             bEnable1 = bEnable2 = TRUE;
  387.             if (_stricmp(szRegVerb0, strEditVerb) == 0)
  388.             {
  389.                 pszVerb1 = szRegVerb1;
  390.                 m_iVerb1 = 1;
  391.                 // verb 2 is already edit
  392.             }
  393.             else if (_stricmp(szRegVerb1, strEditVerb) == 0)
  394.             {
  395.                 pszVerb1 = szRegVerb0;
  396.                 // verb 2 is already edit
  397.             }
  398.             else
  399.             {
  400.                 pszVerb1 = szRegVerb0;
  401.                 pszVerb2 = szRegVerb1;
  402.                 m_iVerb2 = 1;
  403.             }
  404.         }
  405.     }
  406.  
  407.     SmartChangeButton(GetDlgItem(AFX_IDC_VERB1), pszVerb1, bEnable1);
  408.     SmartChangeButton(GetDlgItem(AFX_IDC_VERB2), pszVerb2, bEnable2);
  409. }
  410.  
  411. /////////////////////////////////////////////////////////////////////////////
  412.  
  413. void COleLinksDlg::DoVerb(UINT iVerb)
  414. {
  415.     ASSERT(m_pSingleSelection != NULL);
  416.  
  417.     if (afxTraceFlags & 0x10)
  418.         TRACE("Executing verb %d on server\n", iVerb);
  419.  
  420.     TRY
  421.         m_pSingleSelection->Activate(iVerb);
  422.     CATCH (COleException, e)
  423.         m_pSingleSelection->ReportError(e->m_status);
  424.     END_CATCH
  425.  
  426.     // End the dialog after launch
  427.     EndDialog(IDOK);
  428. }
  429.  
  430. void COleLinksDlg::OnVerb1()
  431. {
  432.     DoVerb(m_iVerb1);
  433. }
  434.  
  435. void COleLinksDlg::OnVerb2()
  436. {
  437.     DoVerb(m_iVerb2);
  438. }
  439.  
  440. #define FOR_EACH_SELECTED_ITEM(pItem)   \
  441.     CListBox* _pList = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);      \
  442.     int _nTotal = _pList->GetCount();                               \
  443.     for (int _iItem = 0; _iItem < _nTotal; _iItem++)                \
  444.     {                                                               \
  445.         if (_pList->GetSel(_iItem) <= 0)                            \
  446.             continue;       /* not selected */                      \
  447.         COleClientItem* pItem;                                      \
  448.         pItem = (COleClientItem*)GetPtrFromDWord(_pList->GetItemData(_iItem));\
  449.         ASSERT(pItem != NULL);
  450.  
  451. #define UPDATE_SELECTED(pItem)  \
  452.         UpdateSelectedItem(_pList, pItem, _iItem)
  453.  
  454. #define DELETE_SELECTED()       \
  455.         _pList->DeleteString(_iItem);                   \
  456.         _iItem--;   /* for next in the loop */          \
  457.         _nTotal--;  /* for next in the loop */
  458.  
  459. #define END_EACH_SELECTED_ITEM()    \
  460.     }
  461.  
  462.  
  463. static void UpdateSelectedItem(CListBox* pList,
  464.     COleClientItem* pItem, int iItem)
  465. {
  466.     char szInfo[OLE_MAXNAMESIZE * 2];
  467.     FormatLinkInfo(pItem, szInfo, NULL);
  468.     pList->DeleteString(iItem);
  469.     pList->InsertString(iItem, szInfo);
  470.     pList->SetItemData(iItem, GetDWordFromPtr(pItem));
  471.     pList->SetSel(iItem);
  472. }
  473.  
  474.  
  475. void COleLinksDlg::OnAuto()
  476. {
  477.     FOR_EACH_SELECTED_ITEM(pItem)
  478.     {
  479.         pItem->SetLinkUpdateOptions(oleupdate_always);
  480.         UPDATE_SELECTED(pItem);
  481.     }
  482.     END_EACH_SELECTED_ITEM()
  483. }
  484.  
  485. void COleLinksDlg::OnManual()
  486. {
  487.     FOR_EACH_SELECTED_ITEM(pItem)
  488.     {
  489.         pItem->SetLinkUpdateOptions(oleupdate_oncall);
  490.         UPDATE_SELECTED(pItem);
  491.     }
  492.     END_EACH_SELECTED_ITEM()
  493. }
  494.  
  495. void COleLinksDlg::OnUpdate()
  496. {
  497.     FOR_EACH_SELECTED_ITEM(pItem)
  498.     {
  499.         TRY
  500.             pItem->UpdateLink();
  501.         CATCH (COleException, e)
  502.             pItem->ReportError(e->m_status);
  503.         END_CATCH
  504.     }
  505.     END_EACH_SELECTED_ITEM()
  506. }
  507.  
  508. void COleLinksDlg::OnFreeze()
  509. {
  510.     FOR_EACH_SELECTED_ITEM(pItem)
  511.     {
  512.         TRY
  513.         {
  514.             if (pItem->FreezeLink(pItem->GetName()))
  515.             {
  516.                 DELETE_SELECTED();
  517.             }
  518.             else
  519.             {
  520.                 pItem->ReportError(OLE_ERROR_COMM);     // strange error
  521.             }
  522.         }
  523.         CATCH (COleException, e)
  524.         {
  525.             pItem->ReportError(OLE_ERROR_COMM);     // strange error
  526.         }
  527.         END_CATCH
  528.     }
  529.     END_EACH_SELECTED_ITEM()
  530.  
  531.     if (_pList->GetCount() == 0)
  532.         EndDialog(IDOK);
  533. }
  534.  
  535. void COleLinksDlg::OnChange()
  536. {
  537.     // We only support changing of one item at a time
  538.     //  The full UISG UI includes more complicated functionality
  539.     COleClientItem* pItem = m_pSingleSelection;
  540.     ASSERT(pItem != NULL);
  541.     ASSERT(pItem->GetType() == OT_LINK);
  542.  
  543.     HANDLE hData = pItem->GetLinkFormatData();
  544.     ASSERT(hData != NULL);
  545.     LPCSTR lpszData = (LPCSTR)::GlobalLock(hData);
  546.     ASSERT(lpszData != NULL);
  547.  
  548.     UINT cbClassName = _fstrlen(lpszData);
  549.     LPCSTR lpszDoc = lpszData + cbClassName + 1;
  550.     LPCSTR lpszItems = lpszDoc + _fstrlen(lpszDoc) + 1;
  551.  
  552.     char szPath[_MAX_PATH];
  553.     _fstrcpy(szPath, lpszDoc);
  554.  
  555.  
  556.  
  557.     CString title;
  558.     CString filter;
  559.     CFileDialog dlgFile(TRUE, NULL, szPath, 
  560.             OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR, 
  561.             (filter.LoadString(AFX_IDS_ALL_FILES) ? (LPCSTR)filter : NULL),
  562.             this);
  563.  
  564.     if (title.LoadString(AFX_IDS_CHANGE_LINK))
  565.         dlgFile.m_ofn.lpstrTitle = title;
  566.  
  567.     dlgFile.m_ofn.lpstrFile = (LPSTR)szPath; // just fill in my own buffer
  568.  
  569.     if (dlgFile.DoModal() == IDCANCEL)
  570.         return;
  571.  
  572.  
  573.     // change the path name
  574.     HANDLE hNewData = ::GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT,
  575.         cbClassName + 1 + _fstrlen(szPath) + 1 + _fstrlen(lpszItems) + 1 + 1);
  576.     if (hNewData == NULL)
  577.     {
  578.         pItem->ReportError(OLE_ERROR_MEMORY);
  579.         return;
  580.     }
  581.     LPSTR lpszNew = (LPSTR)::GlobalLock(hNewData);
  582.     ASSERT(lpszNew != NULL);
  583.  
  584.     // copy the old class name, new doc name and old item names
  585.     _fstrcpy(lpszNew, lpszData);
  586.     lpszNew += cbClassName + 1;
  587.     _fstrcpy(lpszNew, szPath);
  588.     lpszNew += _fstrlen(lpszNew) + 1;
  589.     _fstrcpy(lpszNew, lpszItems);
  590.     lpszNew += _fstrlen(lpszNew) + 1;
  591.     *lpszNew = '\0';        // terminate it
  592.  
  593.     pItem->SetData((OLECLIPFORMAT)::RegisterClipboardFormat("ObjectLink"), 
  594.                 hNewData);
  595.     // update the selection in the listbox
  596.     UpdateSelectedItem((CListBox*)GetDlgItem(AFX_IDC_LISTBOX),
  597.         m_pSingleSelection, m_iSingleSelection);
  598. }
  599.  
  600.  
  601. /////////////////////////////////////////////////////////////////////////////
  602. // Public interface for running modal dialog
  603.  
  604. BOOL AfxOleLinksDialog(COleClientDoc* pDoc)
  605. {
  606.     COleLinksDlg dlg(pDoc);
  607.  
  608.     return (dlg.DoModal() == IDOK);
  609. }
  610.  
  611. /////////////////////////////////////////////////////////////////////////////
  612.