mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1541 lines
55 KiB
1541 lines
55 KiB
/*
|
|
* links.c
|
|
*
|
|
* Implements the OleUIEditLinks function which invokes the complete
|
|
* Edit Links dialog.
|
|
*
|
|
* Copyright (c)1992 Microsoft Corporation, All Right Reserved
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
#include "common.h"
|
|
#include "utility.h"
|
|
#include <commdlg.h>
|
|
#include <dlgs.h>
|
|
#include <stdlib.h>
|
|
|
|
OLEDBGDATA
|
|
|
|
// INTERNAL INFORMATION STARTS HERE
|
|
#define OLEUI_SZMAX 255
|
|
#define LINKTYPELEN 30 // was 9, now I've more than tripled it
|
|
#define szNULL TEXT("\0")
|
|
|
|
typedef UINT (CALLBACK* COMMDLGHOOKPROC)(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
// Internally used structure
|
|
|
|
typedef struct tagLINKINFO
|
|
{
|
|
DWORD dwLink; // app specific identifier of a link
|
|
LPTSTR lpszDisplayName; // file based part of name
|
|
LPTSTR lpszItemName; // object part of name
|
|
LPTSTR lpszShortFileName; // filename without path
|
|
LPTSTR lpszShortLinkType; // Short link type - progID
|
|
LPTSTR lpszFullLinkType; // Full link type - user friendly name
|
|
LPTSTR lpszAMX; // Is the link auto (A) man (M) or dead (X)
|
|
ULONG clenFileName; // count of file part of mon.
|
|
BOOL fSourceAvailable; // bound or not - on boot assume yes??
|
|
BOOL fIsAuto; // 1 =automatic, 0=manual update
|
|
BOOL fIsMarked; // 1 = marked, 0 = not
|
|
BOOL fDontFree; // Don't free this data since it's being reused
|
|
BOOL fIsSelected; // item selected or to be selected
|
|
} LINKINFO, FAR* LPLINKINFO;
|
|
|
|
typedef struct tagEDITLINKS
|
|
{
|
|
// Keep this item first as the Standard* functions depend on it here.
|
|
LPOLEUIEDITLINKS lpOEL; // Original structure passed.
|
|
UINT nIDD; // IDD of dialog (used for help info)
|
|
|
|
BOOL fClose; // Does the button read cancel (0) or
|
|
// close (1)?
|
|
BOOL fItemsExist; // TRUE, items in lbox, FALSE, none
|
|
UINT nChgSrcHelpID; // ID for Help callback from ChangeSrc dlg
|
|
TCHAR szClose[50]; // Text for Close button
|
|
// (when Cancel button gets renamed)
|
|
int nColPos[3]; // tab positions for list box
|
|
int nHeightLine; // height of each line in owner draw listbox
|
|
int nMaxCharWidth; // maximim width of text in owner draw listbox
|
|
|
|
} EDITLINKS, *PEDITLINKS, FAR *LPEDITLINKS;
|
|
|
|
// Internal function prototypes
|
|
// LINKS.CPP
|
|
|
|
INT_PTR CALLBACK EditLinksDialogProc(HWND, UINT, WPARAM, LPARAM);
|
|
BOOL FEditLinksInit(HWND, WPARAM, LPARAM);
|
|
BOOL Container_ChangeSource(HWND, LPEDITLINKS);
|
|
HRESULT Container_AutomaticManual(HWND, BOOL, LPEDITLINKS);
|
|
HRESULT CancelLink(HWND, LPEDITLINKS);
|
|
HRESULT Container_UpdateNow(HWND, LPEDITLINKS);
|
|
HRESULT Container_OpenSource(HWND, LPEDITLINKS);
|
|
int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI,
|
|
BOOL fGetSelected);
|
|
VOID BreakString(LPLINKINFO);
|
|
int GetSelectedItems(HWND, int FAR* FAR*);
|
|
VOID InitControls(HWND hDlg, LPEDITLINKS lpEL);
|
|
VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect);
|
|
VOID ChangeAllLinks(HWND hLIstBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo);
|
|
int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr);
|
|
VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr);
|
|
|
|
|
|
/*
|
|
* OleUIEditLinks
|
|
*
|
|
* Purpose:
|
|
* Invokes the standard OLE Edit Links dialog box allowing the user
|
|
* to manipulate ole links (delete, update, change source, etc).
|
|
*
|
|
* Parameters:
|
|
* lpEL LPOLEUIEditLinks pointing to the in-out structure
|
|
* for this dialog.
|
|
*
|
|
* Return Value:
|
|
* UINT One of the following codes, indicating success or error:
|
|
* OLEUI_SUCCESS Success
|
|
* OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong
|
|
*/
|
|
STDAPI_(UINT) OleUIEditLinks(LPOLEUIEDITLINKS lpEL)
|
|
{
|
|
HGLOBAL hMemDlg = NULL;
|
|
UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpEL, sizeof(OLEUIEDITLINKS),
|
|
&hMemDlg);
|
|
|
|
if (OLEUI_SUCCESS != uRet)
|
|
return uRet;
|
|
|
|
// Validate interface.
|
|
if (NULL == lpEL->lpOleUILinkContainer)
|
|
{
|
|
uRet = OLEUI_ELERR_LINKCNTRNULL;
|
|
}
|
|
else if(IsBadReadPtr(lpEL->lpOleUILinkContainer, sizeof(IOleUILinkContainer)))
|
|
{
|
|
uRet = OLEUI_ELERR_LINKCNTRINVALID;
|
|
}
|
|
|
|
if (OLEUI_SUCCESS != uRet)
|
|
{
|
|
return(uRet);
|
|
}
|
|
|
|
UINT nIDD = bWin4 ? IDD_EDITLINKS4 : IDD_EDITLINKS;
|
|
|
|
// Now that we've validated everything, we can invoke the dialog.
|
|
uRet = UStandardInvocation(EditLinksDialogProc, (LPOLEUISTANDARD)lpEL,
|
|
hMemDlg, MAKEINTRESOURCE(nIDD));
|
|
return uRet;
|
|
}
|
|
|
|
/*
|
|
* EditLinksDialogProc
|
|
*
|
|
* Purpose:
|
|
* Implements the OLE Edit Links dialog as invoked through the
|
|
* OleUIEditLinks function.
|
|
*
|
|
* Parameters:
|
|
* Standard
|
|
*
|
|
* Return Value:
|
|
* Standard
|
|
*/
|
|
INT_PTR CALLBACK EditLinksDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// Declare Win16/Win32 compatible WM_COMMAND parameters.
|
|
COMMANDPARAMS(wID, wCode, hWndMsg);
|
|
|
|
// This will fail under WM_INITDIALOG, where we allocate it.
|
|
UINT uRet = 0;
|
|
LPEDITLINKS lpEL = (LPEDITLINKS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
|
|
|
|
// If the hook processed the message, we're done.
|
|
if (0 != uRet)
|
|
return (BOOL)uRet;
|
|
|
|
//Process help message from secondary dialog
|
|
if ((iMsg == uMsgHelp) && (lpEL))
|
|
{
|
|
PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp, wParam, lParam);
|
|
return FALSE;
|
|
}
|
|
|
|
// Process the temination message
|
|
if (iMsg == uMsgEndDialog)
|
|
{
|
|
EndDialog(hDlg, wParam);
|
|
return TRUE;
|
|
}
|
|
|
|
switch (iMsg)
|
|
{
|
|
case WM_DESTROY:
|
|
if (lpEL)
|
|
{
|
|
StandardCleanup(lpEL, hDlg);
|
|
}
|
|
break;
|
|
case WM_INITDIALOG:
|
|
return FEditLinksInit(hDlg, wParam, lParam);
|
|
|
|
case WM_MEASUREITEM:
|
|
{
|
|
LPMEASUREITEMSTRUCT lpMIS = (LPMEASUREITEMSTRUCT)lParam;
|
|
int nHeightLine;
|
|
|
|
if (lpEL && lpEL->nHeightLine != -1)
|
|
{
|
|
// use cached height
|
|
nHeightLine = lpEL->nHeightLine;
|
|
}
|
|
else
|
|
{
|
|
HFONT hFont;
|
|
HDC hDC;
|
|
TEXTMETRIC tm;
|
|
|
|
hFont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0L);
|
|
|
|
if (hFont == NULL)
|
|
hFont = (HFONT)GetStockObject(SYSTEM_FONT);
|
|
|
|
hDC = GetDC(hDlg);
|
|
hFont = (HFONT)SelectObject(hDC, hFont);
|
|
|
|
GetTextMetrics(hDC, &tm);
|
|
nHeightLine = tm.tmHeight;
|
|
|
|
if (lpEL)
|
|
{
|
|
lpEL->nHeightLine = nHeightLine;
|
|
lpEL->nMaxCharWidth = tm.tmMaxCharWidth;
|
|
}
|
|
ReleaseDC(hDlg, hDC);
|
|
}
|
|
lpMIS->itemHeight = nHeightLine;
|
|
}
|
|
break;
|
|
|
|
case WM_DRAWITEM:
|
|
{
|
|
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
|
|
LPLINKINFO lpLI = (LPLINKINFO)lpDIS->itemData;
|
|
|
|
if ((int)lpDIS->itemID < 0)
|
|
break;
|
|
|
|
if ((ODA_DRAWENTIRE | ODA_SELECT) & lpDIS->itemAction)
|
|
{
|
|
HBRUSH hbr;
|
|
COLORREF crText;
|
|
if (ODS_SELECTED & lpDIS->itemState)
|
|
{
|
|
/*Get proper txt colors */
|
|
crText = SetTextColor(lpDIS->hDC,
|
|
GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
|
|
lpLI->fIsSelected = TRUE;
|
|
}
|
|
else
|
|
{
|
|
hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
|
|
lpLI->fIsSelected = FALSE;
|
|
}
|
|
|
|
FillRect(lpDIS->hDC, &lpDIS->rcItem, hbr);
|
|
DeleteObject(hbr);
|
|
|
|
int nOldBkMode = SetBkMode(lpDIS->hDC, TRANSPARENT);
|
|
|
|
RECT rcClip;
|
|
if (lpLI->lpszDisplayName)
|
|
{
|
|
TCHAR szTemp[MAX_PATH];
|
|
lstrcpy(szTemp, lpLI->lpszDisplayName);
|
|
LPTSTR lpsz = ChopText(
|
|
lpDIS->hwndItem,
|
|
lpEL->nColPos[1] - lpEL->nColPos[0]
|
|
- (lpEL->nMaxCharWidth > 0 ?
|
|
lpEL->nMaxCharWidth : 5),
|
|
szTemp, 0
|
|
);
|
|
rcClip.left = lpDIS->rcItem.left + lpEL->nColPos[0];
|
|
rcClip.top = lpDIS->rcItem.top;
|
|
rcClip.right = lpDIS->rcItem.left + lpEL->nColPos[1]
|
|
- (lpEL->nMaxCharWidth > 0 ?
|
|
lpEL->nMaxCharWidth : 5);
|
|
rcClip.bottom = lpDIS->rcItem.bottom;
|
|
ExtTextOut(
|
|
lpDIS->hDC,
|
|
rcClip.left,
|
|
rcClip.top,
|
|
ETO_CLIPPED,
|
|
(LPRECT)&rcClip,
|
|
lpsz,
|
|
lstrlen(lpsz),
|
|
NULL
|
|
);
|
|
}
|
|
if (lpLI->lpszShortLinkType)
|
|
{
|
|
rcClip.left = lpDIS->rcItem.left + lpEL->nColPos[1];
|
|
rcClip.top = lpDIS->rcItem.top;
|
|
rcClip.right = lpDIS->rcItem.left + lpEL->nColPos[2]
|
|
- (lpEL->nMaxCharWidth > 0 ?
|
|
lpEL->nMaxCharWidth : 5);
|
|
rcClip.bottom = lpDIS->rcItem.bottom;
|
|
ExtTextOut(
|
|
lpDIS->hDC,
|
|
rcClip.left,
|
|
rcClip.top,
|
|
ETO_CLIPPED,
|
|
(LPRECT)&rcClip,
|
|
lpLI->lpszShortLinkType,
|
|
lstrlen(lpLI->lpszShortLinkType),
|
|
NULL
|
|
);
|
|
}
|
|
if (lpLI->lpszAMX)
|
|
{
|
|
rcClip.left = lpDIS->rcItem.left + lpEL->nColPos[2];
|
|
rcClip.top = lpDIS->rcItem.top;
|
|
rcClip.right = lpDIS->rcItem.right;
|
|
rcClip.bottom = lpDIS->rcItem.bottom;
|
|
ExtTextOut(
|
|
lpDIS->hDC,
|
|
rcClip.left,
|
|
rcClip.top,
|
|
ETO_CLIPPED,
|
|
(LPRECT)&rcClip,
|
|
lpLI->lpszAMX,
|
|
lstrlen(lpLI->lpszAMX),
|
|
NULL
|
|
);
|
|
}
|
|
|
|
SetBkMode(lpDIS->hDC, nOldBkMode);
|
|
|
|
// restore orig colors if we changed them
|
|
if (ODS_SELECTED & lpDIS->itemState)
|
|
SetTextColor(lpDIS->hDC, crText);
|
|
|
|
}
|
|
if (ODA_FOCUS & lpDIS->itemAction)
|
|
DrawFocusRect(lpDIS->hDC, &lpDIS->rcItem);
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_DELETEITEM:
|
|
{
|
|
LPDELETEITEMSTRUCT lpDIS = (LPDELETEITEMSTRUCT)lParam;
|
|
UINT idCtl = (UINT)wParam;
|
|
LPLINKINFO lpLI = (LPLINKINFO)lpDIS->itemData;
|
|
|
|
if (lpLI->lpszDisplayName)
|
|
OleStdFree((LPVOID)lpLI->lpszDisplayName);
|
|
if (lpLI->lpszShortLinkType)
|
|
OleStdFree((LPVOID)lpLI->lpszShortLinkType);
|
|
if (lpLI->lpszFullLinkType)
|
|
OleStdFree((LPVOID)lpLI->lpszFullLinkType);
|
|
|
|
/* The ChangeSource processing reuses allocated space for
|
|
** links that have been modified.
|
|
*/
|
|
// Don't free the LINKINFO for the changed links
|
|
if (lpLI->fDontFree)
|
|
lpLI->fDontFree = FALSE;
|
|
else
|
|
{
|
|
if (lpLI->lpszAMX)
|
|
OleStdFree((LPVOID)lpLI->lpszAMX);
|
|
OleStdFree((LPVOID)lpLI);
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_COMPAREITEM:
|
|
{
|
|
LPCOMPAREITEMSTRUCT lpCIS = (LPCOMPAREITEMSTRUCT)lParam;
|
|
LPLINKINFO lpLI1 = (LPLINKINFO)lpCIS->itemData1;
|
|
LPLINKINFO lpLI2 = (LPLINKINFO)lpCIS->itemData2;
|
|
|
|
// Sort list entries by DisplayName
|
|
return lstrcmp(lpLI1->lpszDisplayName, lpLI2->lpszDisplayName);
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
switch (wID)
|
|
{
|
|
case IDC_EL_CHANGESOURCE:
|
|
{
|
|
BOOL fRet = Container_ChangeSource(hDlg, lpEL);
|
|
if (!fRet)
|
|
PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
|
|
MB_ICONEXCLAMATION | MB_OK);
|
|
InitControls(hDlg, lpEL);
|
|
}
|
|
break;
|
|
|
|
case IDC_EL_AUTOMATIC:
|
|
{
|
|
CheckDlgButton(hDlg, IDC_EL_AUTOMATIC, 1);
|
|
CheckDlgButton(hDlg, IDC_EL_MANUAL, 0);
|
|
|
|
HRESULT hErr = Container_AutomaticManual(hDlg, TRUE, lpEL);
|
|
if (hErr != NOERROR)
|
|
PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
|
|
MB_ICONEXCLAMATION | MB_OK);
|
|
|
|
InitControls(hDlg, lpEL);
|
|
}
|
|
break;
|
|
|
|
case IDC_EL_MANUAL:
|
|
{
|
|
CheckDlgButton(hDlg, IDC_EL_MANUAL, 1);
|
|
CheckDlgButton(hDlg, IDC_EL_AUTOMATIC, 0);
|
|
|
|
HRESULT hErr = Container_AutomaticManual(hDlg, FALSE, lpEL);
|
|
if (hErr != NOERROR)
|
|
PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
|
|
MB_ICONEXCLAMATION | MB_OK);
|
|
|
|
InitControls(hDlg, lpEL);
|
|
}
|
|
break;
|
|
|
|
case IDC_EL_CANCELLINK:
|
|
CancelLink(hDlg,lpEL);
|
|
InitControls(hDlg, lpEL);
|
|
break;
|
|
|
|
case IDC_EL_UPDATENOW:
|
|
Container_UpdateNow(hDlg, lpEL);
|
|
InitControls(hDlg, lpEL);
|
|
break;
|
|
|
|
case IDC_EL_OPENSOURCE:
|
|
{
|
|
HRESULT hErr = Container_OpenSource(hDlg, lpEL);
|
|
if (hErr != NOERROR)
|
|
{
|
|
InitControls(hDlg, lpEL);
|
|
// Don't close dialog
|
|
break;
|
|
}
|
|
SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
|
|
} // fall through
|
|
|
|
case IDC_EL_LINKSLISTBOX:
|
|
if (wCode == LBN_SELCHANGE)
|
|
InitControls(hDlg, lpEL);
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
|
|
break;
|
|
|
|
case IDC_OLEUIHELP:
|
|
PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp,
|
|
(WPARAM)hDlg, MAKELPARAM(IDD_EDITLINKS, 0));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (lpEL != NULL && iMsg == lpEL->nChgSrcHelpID)
|
|
{
|
|
PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp,
|
|
(WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0));
|
|
}
|
|
if (iMsg == uMsgBrowseOFN &&
|
|
lpEL != NULL && lpEL->lpOEL && lpEL->lpOEL->hWndOwner)
|
|
{
|
|
SendMessage(lpEL->lpOEL->hWndOwner, uMsgBrowseOFN, wParam, lParam);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* FEditLinksInit
|
|
*
|
|
* Purpose:
|
|
* WM_INITIDIALOG handler for the Edit Links dialog box.
|
|
*
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND of the dialog
|
|
* wParam WPARAM of the message
|
|
* lParam LPARAM of the message
|
|
*
|
|
* Return Value:
|
|
* BOOL Value to return for WM_INITDIALOG.
|
|
*/
|
|
BOOL FEditLinksInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// Copy the structure at lParam into our instance memory.
|
|
HFONT hFont;
|
|
LPEDITLINKS lpEL = (LPEDITLINKS)LpvStandardInit(hDlg, sizeof(EDITLINKS), &hFont);
|
|
|
|
// PvStandardInit send a termination to us already.
|
|
if (NULL == lpEL)
|
|
return FALSE;
|
|
|
|
LPOLEUIEDITLINKS lpOEL = (LPOLEUIEDITLINKS)lParam;
|
|
lpEL->lpOEL = lpOEL;
|
|
lpEL->nIDD = IDD_EDITLINKS;
|
|
|
|
// metrics unknown so far
|
|
lpEL->nHeightLine = -1;
|
|
lpEL->nMaxCharWidth = -1;
|
|
|
|
/* calculate the column positions relative to the listbox */
|
|
HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
|
|
RECT rc;
|
|
GetWindowRect(hListBox, (LPRECT)&rc);
|
|
int nStart = rc.left;
|
|
GetWindowRect(GetDlgItem(hDlg, IDC_EL_COL1), (LPRECT)&rc);
|
|
lpEL->nColPos[0] = rc.left - nStart;
|
|
GetWindowRect(GetDlgItem(hDlg, IDC_EL_COL2), (LPRECT)&rc);
|
|
lpEL->nColPos[1] = rc.left - nStart;
|
|
GetWindowRect(GetDlgItem(hDlg, IDC_EL_COL3), (LPRECT)&rc);
|
|
lpEL->nColPos[2] = rc.left - nStart;
|
|
|
|
LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
|
|
|
ULONG cLinks = LoadLinkLB(hListBox, lpOleUILinkCntr);
|
|
if ((int)cLinks < 0)
|
|
return FALSE;
|
|
|
|
BOOL fDlgItem = (BOOL)cLinks;
|
|
lpEL->fItemsExist = (BOOL)cLinks;
|
|
|
|
InitControls(hDlg, lpEL);
|
|
|
|
// Copy other information from lpOEL that we might modify.
|
|
|
|
// If we got a font, send it to the necessary controls.
|
|
if (NULL != hFont)
|
|
{
|
|
// Do this for as many controls as you need it for.
|
|
// SendDlgItemMessage(hDlg, ID_<UFILL>, WM_SETFONT, (WPARAM)hFont, 0L);
|
|
}
|
|
|
|
// Show or hide the help button
|
|
if (!(lpEL->lpOEL->dwFlags & ELF_SHOWHELP))
|
|
StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE);
|
|
|
|
/*
|
|
* PERFORM OTHER INITIALIZATION HERE. ON ANY LoadString
|
|
* FAILURE POST OLEUI_MSG_ENDDIALOG WITH OLEUI_ERR_LOADSTRING.
|
|
*/
|
|
|
|
// If requested disable UpdateNow button
|
|
if ((lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW))
|
|
StandardShowDlgItem(hDlg, IDC_EL_UPDATENOW, SW_HIDE);
|
|
|
|
// If requested disable OpenSource button
|
|
if ((lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE))
|
|
StandardShowDlgItem(hDlg, IDC_EL_OPENSOURCE, SW_HIDE);
|
|
|
|
// If requested disable UpdateNow button
|
|
if ((lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE))
|
|
StandardShowDlgItem(hDlg, IDC_EL_CHANGESOURCE, SW_HIDE);
|
|
|
|
// If requested disable CancelLink button
|
|
if ((lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK))
|
|
StandardShowDlgItem(hDlg, IDC_EL_CANCELLINK, SW_HIDE);
|
|
|
|
// Change the caption
|
|
if (NULL!=lpOEL->lpszCaption)
|
|
SetWindowText(hDlg, lpOEL->lpszCaption);
|
|
|
|
// Load 'Close' string used to rename Cancel button
|
|
int n = LoadString(_g_hOleStdResInst, IDS_CLOSE, lpEL->szClose, sizeof(lpEL->szClose)/sizeof(TCHAR));
|
|
if (!n)
|
|
{
|
|
PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
|
|
return FALSE;
|
|
}
|
|
|
|
if (cLinks > 0)
|
|
SetFocus(hListBox);
|
|
else
|
|
SetFocus(GetDlgItem(hDlg, IDCANCEL));
|
|
|
|
lpEL->nChgSrcHelpID = RegisterWindowMessage(HELPMSGSTRING);
|
|
|
|
// Call the hook with lCustData in lParam
|
|
UStandardHook(lpEL, hDlg, WM_INITDIALOG, wParam, lpOEL->lCustData);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Container_ChangeSource
|
|
*
|
|
* Purpose:
|
|
* Tunnel to File Open type dlg and allow user to select new file
|
|
* for file based monikers, OR to change the whole moniker to what
|
|
* the user types into the editable field.
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND of the dialog
|
|
* LPEDITLINKS Pointer to EditLinks structure (contains all nec.
|
|
* info)
|
|
*
|
|
* Return Value:
|
|
* BOOL for now, because we are not using any ole functions
|
|
* to return an HRESULT.
|
|
* HRESULT HRESULT value indicating success or failure of
|
|
* changing the moniker value
|
|
*/
|
|
|
|
BOOL Container_ChangeSource(HWND hDlg, LPEDITLINKS lpEL)
|
|
{
|
|
HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
|
|
int FAR* rgIndex;
|
|
int cSelItems = GetSelectedItems(hListBox, &rgIndex);
|
|
|
|
if (cSelItems < 0)
|
|
return FALSE;
|
|
|
|
if (!cSelItems)
|
|
return TRUE;
|
|
|
|
OLEUICHANGESOURCE cs; memset(&cs, 0, sizeof(cs));
|
|
cs.cbStruct = sizeof(cs);
|
|
cs.hWndOwner = hDlg;
|
|
if (lpEL->lpOEL->dwFlags & ELF_SHOWHELP)
|
|
cs.dwFlags |= CSF_SHOWHELP;
|
|
|
|
LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
|
cs.lpOleUILinkContainer = lpOleUILinkCntr;
|
|
|
|
for (int i = cSelItems-1; i >= 0; i--)
|
|
{
|
|
// allow caller to customize the change source dialog
|
|
LPLINKINFO lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0);
|
|
cs.lpszDisplayName = lpLI->lpszDisplayName;
|
|
cs.dwLink = lpLI->dwLink;
|
|
cs.nFileLength = lpLI->clenFileName;
|
|
|
|
UINT uRet = UStandardHook(lpEL, hDlg, uMsgChangeSource, 0, (LPARAM)&cs);
|
|
if (!uRet)
|
|
uRet = (OLEUI_OK == OleUIChangeSource(&cs));
|
|
if (!uRet)
|
|
break; // dialog canceled (cancel for all)
|
|
|
|
if (!lpEL->fClose)
|
|
{
|
|
SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose);
|
|
lpEL->fClose = TRUE;
|
|
}
|
|
|
|
// update the list box item for the new name
|
|
// (note: original lpszDisplayName already freed)
|
|
lpLI->fSourceAvailable = (cs.dwFlags & CSF_VALIDSOURCE);
|
|
lpLI->lpszDisplayName = cs.lpszDisplayName;
|
|
UpdateLinkLBItem(hListBox, rgIndex[i], lpEL, TRUE);
|
|
|
|
// if differed only in file name, allow user to change all links
|
|
if (cs.lpszFrom != NULL && cs.lpszTo != NULL)
|
|
ChangeAllLinks(hListBox, lpOleUILinkCntr, cs.lpszFrom, cs.lpszTo);
|
|
|
|
// must free and NULL out the lpszFrom and lpszTo OUT fields
|
|
OleStdFree(cs.lpszFrom);
|
|
cs.lpszFrom = NULL;
|
|
OleStdFree(cs.lpszTo);
|
|
cs.lpszTo = NULL;
|
|
}
|
|
|
|
if (rgIndex != NULL)
|
|
OleStdFree(rgIndex);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Container_AutomaticManual
|
|
*
|
|
* Purpose:
|
|
* To change the selected moniker to manual or automatic update.
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND of the dialog
|
|
* FAutoMan Flag indicating AUTO (TRUE/1) or MANUAL(FALSE/0)
|
|
* LPEDITLINKS Pointer to EditLinks structure (contains all nec.
|
|
* info)
|
|
* * this may change - don't know how the linked list
|
|
* * of multi-selected items will work.
|
|
* Return Value:
|
|
* HRESULT HRESULT value indicating success or failure of
|
|
* changing the moniker value
|
|
*/
|
|
|
|
HRESULT Container_AutomaticManual(HWND hDlg, BOOL fAutoMan, LPEDITLINKS lpEL)
|
|
{
|
|
HRESULT hErr = NOERROR;
|
|
int cSelItems;
|
|
int FAR* rgIndex;
|
|
int i = 0;
|
|
LPLINKINFO lpLI;
|
|
LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
|
HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
|
|
BOOL bUpdate = FALSE;
|
|
|
|
OleDbgAssert(lpOleUILinkCntr);
|
|
|
|
/* Change so looks at flag in structure. Only update those that
|
|
need to be updated. Make sure to change flag if status changes.
|
|
*/
|
|
|
|
cSelItems = GetSelectedItems(hListBox, &rgIndex);
|
|
|
|
if (cSelItems < 0)
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
if (!cSelItems)
|
|
return NOERROR;
|
|
|
|
HCURSOR hCursorOld = HourGlassOn();
|
|
|
|
if (!lpEL->fClose)
|
|
{
|
|
SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose);
|
|
lpEL->fClose = TRUE;
|
|
}
|
|
|
|
for (i = 0; i < cSelItems; i++)
|
|
{
|
|
lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0);
|
|
if (fAutoMan)
|
|
{
|
|
// If switching to AUTOMATIC
|
|
if (!lpLI->fIsAuto) // Only change MANUAL links
|
|
{
|
|
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n"));
|
|
hErr=lpOleUILinkCntr->SetLinkUpdateOptions(
|
|
lpLI->dwLink,
|
|
OLEUPDATE_ALWAYS
|
|
);
|
|
OLEDBG_END2
|
|
|
|
lpLI->fIsAuto=TRUE;
|
|
lpLI->fIsMarked = TRUE;
|
|
bUpdate = TRUE;
|
|
}
|
|
}
|
|
else // If switching to MANUAL
|
|
{
|
|
if (lpLI->fIsAuto) // Only do AUTOMATIC Links
|
|
{
|
|
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n"));
|
|
hErr=lpOleUILinkCntr->SetLinkUpdateOptions(
|
|
lpLI->dwLink,
|
|
OLEUPDATE_ONCALL
|
|
);
|
|
OLEDBG_END2
|
|
|
|
lpLI->fIsAuto = FALSE;
|
|
lpLI->fIsMarked = TRUE;
|
|
bUpdate = TRUE;
|
|
}
|
|
}
|
|
|
|
if (hErr != NOERROR)
|
|
{
|
|
OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::SetLinkUpdateOptions returned"),hErr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bUpdate)
|
|
RefreshLinkLB(hListBox, lpOleUILinkCntr);
|
|
|
|
if (rgIndex)
|
|
OleStdFree((LPVOID)rgIndex);
|
|
|
|
HourGlassOff(hCursorOld);
|
|
|
|
return hErr;
|
|
}
|
|
|
|
HRESULT CancelLink(HWND hDlg, LPEDITLINKS lpEL)
|
|
{
|
|
HRESULT hErr;
|
|
LPMONIKER lpmk;
|
|
int cSelItems;
|
|
int FAR* rgIndex;
|
|
int i = 0;
|
|
LPLINKINFO lpLI;
|
|
LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
|
HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
|
|
BOOL bUpdate = FALSE;
|
|
|
|
OleDbgAssert(lpOleUILinkCntr);
|
|
|
|
lpmk = NULL;
|
|
|
|
cSelItems = GetSelectedItems(hListBox, &rgIndex);
|
|
|
|
if (cSelItems < 0)
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
if (!cSelItems)
|
|
return NOERROR;
|
|
|
|
HCURSOR hCursorOld = HourGlassOn();
|
|
|
|
for (i = 0; i < cSelItems; i++)
|
|
{
|
|
lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0);
|
|
|
|
UINT uRet = PopupMessage(hDlg, IDS_LINKS,
|
|
IDS_CONFIRMBREAKLINK, MB_YESNO|MB_ICONQUESTION);
|
|
if (uRet == IDNO)
|
|
break;
|
|
|
|
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::CancelLink called\r\n"));
|
|
hErr = lpOleUILinkCntr->CancelLink(lpLI->dwLink);
|
|
OLEDBG_END2
|
|
|
|
if (!lpEL->fClose)
|
|
{
|
|
SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose);
|
|
lpEL->fClose = TRUE;
|
|
}
|
|
|
|
if (hErr != NOERROR)
|
|
{
|
|
OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::CancelLink returned"),hErr);
|
|
lpLI->fIsMarked = TRUE;
|
|
bUpdate = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Delete links that we make null from listbox
|
|
SendMessage(hListBox, LB_DELETESTRING, (WPARAM) rgIndex[i], 0L);
|
|
int i2;
|
|
for (i2 = i + 1; i2 < cSelItems; i2++)
|
|
{
|
|
if (rgIndex[i2] > rgIndex[i])
|
|
rgIndex[i2]--;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bUpdate)
|
|
RefreshLinkLB(hListBox, lpOleUILinkCntr);
|
|
|
|
if (rgIndex)
|
|
OleStdFree((LPVOID)rgIndex);
|
|
|
|
HourGlassOff(hCursorOld);
|
|
|
|
return hErr;
|
|
}
|
|
|
|
/*
|
|
* Container_UpdateNow
|
|
*
|
|
* Purpose:
|
|
* Immediately force an update for all (manual) links
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND of the dialog
|
|
* LPEDITLINKS Pointer to EditLinks structure (contains all nec. info)
|
|
* * this may change - don't know how the linked list
|
|
* * of multi-selected items will work.
|
|
* Return Value:
|
|
* HRESULT HRESULT value indicating success or failure of
|
|
* changing the moniker value
|
|
*/
|
|
HRESULT Container_UpdateNow(HWND hDlg, LPEDITLINKS lpEL)
|
|
{
|
|
HRESULT hErr;
|
|
LPLINKINFO lpLI;
|
|
int cSelItems;
|
|
int FAR* rgIndex;
|
|
int i = 0;
|
|
LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
|
HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
|
|
BOOL bUpdate = FALSE;
|
|
|
|
OleDbgAssert(lpOleUILinkCntr);
|
|
|
|
cSelItems = GetSelectedItems(hListBox, &rgIndex);
|
|
|
|
if (cSelItems < 0)
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
if (!cSelItems)
|
|
return NOERROR;
|
|
|
|
HCURSOR hCursorOld = HourGlassOn();
|
|
|
|
if (!lpEL->fClose)
|
|
{
|
|
SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose);
|
|
lpEL->fClose = TRUE;
|
|
}
|
|
|
|
for (i = 0; i < cSelItems; i++)
|
|
{
|
|
lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0);
|
|
|
|
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::UpdateLink called\r\n"));
|
|
hErr = lpOleUILinkCntr->UpdateLink(
|
|
lpLI->dwLink,
|
|
TRUE,
|
|
FALSE
|
|
);
|
|
OLEDBG_END2
|
|
bUpdate = TRUE;
|
|
lpLI->fIsMarked = TRUE;
|
|
|
|
if (hErr != NOERROR)
|
|
{
|
|
OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::UpdateLink returned"),hErr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bUpdate)
|
|
RefreshLinkLB(hListBox, lpOleUILinkCntr);
|
|
|
|
if (rgIndex)
|
|
OleStdFree((LPVOID)rgIndex);
|
|
|
|
HourGlassOff(hCursorOld);
|
|
|
|
return hErr;
|
|
|
|
}
|
|
|
|
/*
|
|
* Container_OpenSource
|
|
*
|
|
* Purpose:
|
|
* Immediately force an update for all (manual) links
|
|
*
|
|
* Parameters:
|
|
* hDlg HWND of the dialog
|
|
* LPEDITLINKS Pointer to EditLinks structure (contains all nec.
|
|
* info)
|
|
*
|
|
* Return Value:
|
|
* HRESULT HRESULT value indicating success or failure of
|
|
* changing the moniker value
|
|
*/
|
|
|
|
HRESULT Container_OpenSource(HWND hDlg, LPEDITLINKS lpEL)
|
|
{
|
|
HRESULT hErr;
|
|
int cSelItems;
|
|
int FAR* rgIndex;
|
|
LPLINKINFO lpLI;
|
|
RECT rcPosRect;
|
|
LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
|
HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
|
|
|
|
OleDbgAssert(lpOleUILinkCntr);
|
|
|
|
rcPosRect.top = 0;
|
|
rcPosRect.left = 0;
|
|
rcPosRect.right = 0;
|
|
rcPosRect.bottom = 0;
|
|
|
|
cSelItems = GetSelectedItems(hListBox, &rgIndex);
|
|
|
|
if (cSelItems < 0)
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
if (cSelItems != 1) // can't open source for multiple items
|
|
return NOERROR;
|
|
|
|
HCURSOR hCursorOld = HourGlassOn();
|
|
|
|
if (!lpEL->fClose)
|
|
{
|
|
SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose);
|
|
lpEL->fClose = TRUE;
|
|
}
|
|
|
|
lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[0], 0);
|
|
|
|
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::OpenLinkSource called\r\n"));
|
|
hErr = lpOleUILinkCntr->OpenLinkSource(
|
|
lpLI->dwLink
|
|
);
|
|
OLEDBG_END2
|
|
|
|
UpdateLinkLBItem(hListBox, rgIndex[0], lpEL, TRUE);
|
|
if (hErr != NOERROR) {
|
|
OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::OpenLinkSource returned"),hErr);
|
|
}
|
|
|
|
if (rgIndex)
|
|
OleStdFree((LPVOID)rgIndex);
|
|
|
|
HourGlassOff(hCursorOld);
|
|
|
|
return hErr;
|
|
}
|
|
|
|
/* AddLinkLBItem
|
|
** -------------
|
|
**
|
|
** Add the item pointed to by lpLI to the Link ListBox and return
|
|
** the index of it in the ListBox
|
|
*/
|
|
int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI, BOOL fGetSelected)
|
|
{
|
|
HRESULT hErr;
|
|
DWORD dwUpdateOpt;
|
|
int nIndex;
|
|
|
|
OleDbgAssert(lpOleUILinkCntr && hListBox && lpLI);
|
|
|
|
lpLI->fDontFree = FALSE;
|
|
|
|
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkSource called\r\n"));
|
|
hErr = lpOleUILinkCntr->GetLinkSource(
|
|
lpLI->dwLink,
|
|
(LPTSTR FAR*)&lpLI->lpszDisplayName,
|
|
(ULONG FAR*)&lpLI->clenFileName,
|
|
(LPTSTR FAR*)&lpLI->lpszFullLinkType,
|
|
(LPTSTR FAR*)&lpLI->lpszShortLinkType,
|
|
(BOOL FAR*)&lpLI->fSourceAvailable,
|
|
fGetSelected ? (BOOL FAR*)&lpLI->fIsSelected : NULL
|
|
);
|
|
OLEDBG_END2
|
|
|
|
if (hErr != NOERROR)
|
|
{
|
|
OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkSource returned"),hErr);
|
|
PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKSOURCE,
|
|
MB_ICONEXCLAMATION | MB_OK);
|
|
goto cleanup;
|
|
}
|
|
|
|
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkUpdateOptions called\r\n"));
|
|
hErr=lpOleUILinkCntr->GetLinkUpdateOptions(
|
|
lpLI->dwLink,
|
|
(LPDWORD)&dwUpdateOpt
|
|
);
|
|
OLEDBG_END2
|
|
|
|
if (hErr != NOERROR)
|
|
{
|
|
OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkUpdateOptions returned"),hErr);
|
|
PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKUPDATEOPTIONS,
|
|
MB_ICONEXCLAMATION | MB_OK);
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
if (lpLI->fSourceAvailable)
|
|
{
|
|
if (dwUpdateOpt == OLEUPDATE_ALWAYS)
|
|
{
|
|
lpLI->fIsAuto = TRUE;
|
|
LoadString(_g_hOleStdResInst, IDS_LINK_AUTO, lpLI->lpszAMX,
|
|
(int)OleStdGetSize((LPVOID)lpLI->lpszAMX) / sizeof (TCHAR));
|
|
}
|
|
else
|
|
{
|
|
lpLI->fIsAuto = FALSE;
|
|
LoadString(_g_hOleStdResInst, IDS_LINK_MANUAL, lpLI->lpszAMX,
|
|
(int)OleStdGetSize((LPVOID)lpLI->lpszAMX) / sizeof (TCHAR));
|
|
}
|
|
}
|
|
else
|
|
LoadString(_g_hOleStdResInst, IDS_LINK_UNKNOWN, lpLI->lpszAMX,
|
|
(int)OleStdGetSize((LPVOID)lpLI->lpszAMX) / sizeof (TCHAR));
|
|
|
|
BreakString(lpLI);
|
|
|
|
nIndex = (int)SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0,
|
|
(LPARAM)lpLI);
|
|
|
|
if (nIndex == LB_ERR)
|
|
{
|
|
PopupMessage(hListBox, IDS_LINKS, IDS_ERR_ADDSTRING,
|
|
MB_ICONEXCLAMATION | MB_OK);
|
|
goto cleanup;
|
|
}
|
|
return nIndex;
|
|
|
|
cleanup:
|
|
if (lpLI->lpszDisplayName)
|
|
OleStdFree((LPVOID)lpLI->lpszDisplayName);
|
|
|
|
if (lpLI->lpszShortLinkType)
|
|
OleStdFree((LPVOID)lpLI->lpszShortLinkType);
|
|
|
|
if (lpLI->lpszFullLinkType)
|
|
OleStdFree((LPVOID)lpLI->lpszFullLinkType);
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* BreakString
|
|
* -----------
|
|
*
|
|
* Purpose:
|
|
* Break the lpszDisplayName into various parts
|
|
*
|
|
* Parameters:
|
|
* lpLI pointer to LINKINFO structure
|
|
*
|
|
* Returns:
|
|
*
|
|
*/
|
|
VOID BreakString(LPLINKINFO lpLI)
|
|
{
|
|
LPTSTR lpsz;
|
|
|
|
if (!lpLI->clenFileName ||
|
|
(lstrlen(lpLI->lpszDisplayName)==(int)lpLI->clenFileName))
|
|
{
|
|
lpLI->lpszItemName = NULL;
|
|
}
|
|
else
|
|
{
|
|
lpLI->lpszItemName = lpLI->lpszDisplayName + lpLI->clenFileName;
|
|
}
|
|
|
|
// search from last character of filename
|
|
lpsz = lpLI->lpszDisplayName + lstrlen(lpLI->lpszDisplayName);
|
|
while (lpsz > lpLI->lpszDisplayName)
|
|
{
|
|
lpsz = CharPrev(lpLI->lpszDisplayName, lpsz);
|
|
if ((*lpsz == '\\') || (*lpsz == '/') || (*lpsz == ':'))
|
|
break;
|
|
}
|
|
|
|
if (lpsz == lpLI->lpszDisplayName)
|
|
lpLI->lpszShortFileName = lpsz;
|
|
else
|
|
lpLI->lpszShortFileName = CharNext(lpsz);
|
|
}
|
|
|
|
/* GetSelectedItems
|
|
* ----------------
|
|
*
|
|
* Purpose:
|
|
* Retrieve the indices of the selected items in the listbox
|
|
* Note that *lprgIndex needed to be free after using the function
|
|
*
|
|
* Parameters:
|
|
* hListBox window handle of listbox
|
|
* lprgIndex pointer to an integer array to receive the indices
|
|
* must be freed afterwards
|
|
*
|
|
* Returns:
|
|
* number of indices retrieved, -1 if error
|
|
*/
|
|
int GetSelectedItems(HWND hListBox, int FAR* FAR* lprgIndex)
|
|
{
|
|
DWORD cSelItems;
|
|
DWORD cCheckItems;
|
|
|
|
*lprgIndex = NULL;
|
|
|
|
cSelItems = (DWORD)SendMessage(hListBox, LB_GETSELCOUNT, 0, 0L);
|
|
if ((int)cSelItems < 0) // error
|
|
return (int)cSelItems;
|
|
|
|
if (!cSelItems)
|
|
return 0;
|
|
|
|
*lprgIndex = (int FAR*)OleStdMalloc((int)cSelItems * sizeof(int));
|
|
|
|
cCheckItems = (DWORD)SendMessage(hListBox, LB_GETSELITEMS,
|
|
(WPARAM) cSelItems, (LPARAM) (int FAR *) *lprgIndex);
|
|
|
|
if (cCheckItems == cSelItems)
|
|
return (int)cSelItems;
|
|
else
|
|
{
|
|
if (*lprgIndex)
|
|
OleStdFree((LPVOID)*lprgIndex);
|
|
*lprgIndex = NULL;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* InitControls
|
|
* ------------
|
|
*
|
|
* Purpose:
|
|
* Initialize the state of the Auto/Manual button, Link source/type
|
|
* static field, etc in the dialogs according to the selection in the
|
|
* listbox
|
|
*
|
|
* Parameters:
|
|
* hDlg handle to the dialog window
|
|
*/
|
|
VOID InitControls(HWND hDlg, LPEDITLINKS lpEL)
|
|
{
|
|
int cSelItems;
|
|
HWND hListBox;
|
|
int i;
|
|
int FAR* rgIndex;
|
|
LPLINKINFO lpLI;
|
|
LPTSTR lpszType = NULL;
|
|
LPTSTR lpszSource = NULL;
|
|
int cAuto = 0;
|
|
int cManual = 0;
|
|
BOOL bSameType = TRUE;
|
|
BOOL bSameSource = TRUE;
|
|
TCHAR tsz[MAX_PATH];
|
|
LPTSTR lpsz;
|
|
|
|
hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
|
|
|
|
cSelItems = GetSelectedItems(hListBox, &rgIndex);
|
|
if (cSelItems < 0)
|
|
return;
|
|
|
|
if ((cSelItems > 0) && (rgIndex == NULL))
|
|
return;
|
|
|
|
StandardEnableDlgItem(hDlg, IDC_EL_AUTOMATIC, (BOOL)cSelItems);
|
|
StandardEnableDlgItem(hDlg, IDC_EL_MANUAL, (BOOL)cSelItems);
|
|
if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK))
|
|
StandardEnableDlgItem(hDlg, IDC_EL_CANCELLINK, (BOOL)cSelItems);
|
|
if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE))
|
|
StandardEnableDlgItem(hDlg, IDC_EL_OPENSOURCE, cSelItems == 1);
|
|
if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE))
|
|
StandardEnableDlgItem(hDlg, IDC_EL_CHANGESOURCE, cSelItems == 1);
|
|
if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW))
|
|
StandardEnableDlgItem(hDlg, IDC_EL_UPDATENOW, (BOOL)cSelItems);
|
|
|
|
for (i = 0; i < cSelItems; i++)
|
|
{
|
|
lpLI = (LPLINKINFO)SendDlgItemMessage(hDlg, IDC_EL_LINKSLISTBOX,
|
|
LB_GETITEMDATA, rgIndex[i], 0);
|
|
|
|
if (lpszSource && lpLI->lpszDisplayName)
|
|
{
|
|
if (bSameSource && lstrcmp(lpszSource, lpLI->lpszDisplayName))
|
|
bSameSource = FALSE;
|
|
}
|
|
else
|
|
lpszSource = lpLI->lpszDisplayName;
|
|
|
|
if (lpszType && lpLI->lpszFullLinkType)
|
|
{
|
|
if (bSameType && lstrcmp(lpszType, lpLI->lpszFullLinkType))
|
|
bSameType = FALSE;
|
|
}
|
|
else
|
|
lpszType = lpLI->lpszFullLinkType;
|
|
|
|
if (lpLI->fIsAuto)
|
|
cAuto++;
|
|
else
|
|
cManual++;
|
|
}
|
|
|
|
CheckDlgButton(hDlg, IDC_EL_AUTOMATIC, cAuto && !cManual);
|
|
CheckDlgButton(hDlg, IDC_EL_MANUAL, !cAuto && cManual);
|
|
|
|
/* fill full source in static text box
|
|
** below list
|
|
*/
|
|
if (!bSameSource || !lpszSource)
|
|
lpszSource = szNULL;
|
|
lstrcpy(tsz, lpszSource);
|
|
lpsz = ChopText(GetDlgItem(hDlg, IDC_EL_LINKSOURCE), 0, tsz, 0);
|
|
SetDlgItemText(hDlg, IDC_EL_LINKSOURCE, lpsz);
|
|
|
|
/* fill full link type name in static
|
|
** "type" text box
|
|
*/
|
|
if (!bSameType || !lpszType)
|
|
lpszType = szNULL;
|
|
SetDlgItemText(hDlg, IDC_EL_LINKTYPE, lpszType);
|
|
|
|
if (rgIndex)
|
|
OleStdFree((LPVOID)rgIndex);
|
|
}
|
|
|
|
|
|
/* UpdateLinkLBItem
|
|
* -----------------
|
|
*
|
|
* Purpose:
|
|
* Update the linkinfo struct in the listbox to reflect the changes
|
|
* made by the last operation. It is done simply by removing the item
|
|
* from the listbox and add it back.
|
|
*
|
|
* Parameters:
|
|
* hListBox handle of listbox
|
|
* nIndex index of listbox item
|
|
* lpEL pointer to editlinks structure
|
|
* bSelect select the item or not after update
|
|
*/
|
|
VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect)
|
|
{
|
|
LPLINKINFO lpLI;
|
|
LPOLEUILINKCONTAINER lpOleUILinkCntr;
|
|
|
|
if (!hListBox || (nIndex < 0) || !lpEL)
|
|
return;
|
|
|
|
lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
|
|
|
lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, nIndex, 0);
|
|
|
|
if (lpLI == NULL)
|
|
return;
|
|
|
|
/* Don't free the data associated with this listbox item
|
|
** because we are going to reuse the allocated space for
|
|
** the modified link. WM_DELETEITEM processing in the
|
|
** dialog checks this flag before deleting data
|
|
** associcated with list item.
|
|
*/
|
|
lpLI->fDontFree = TRUE;
|
|
SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L);
|
|
|
|
nIndex = AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE);
|
|
if (bSelect)
|
|
{
|
|
SendMessage(hListBox, LB_SETSEL, TRUE, MAKELPARAM(nIndex, 0));
|
|
SendMessage(hListBox, LB_SETCARETINDEX, nIndex, MAKELPARAM(TRUE, 0));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* ChangeAllLinks
|
|
* --------------
|
|
*
|
|
* Purpose:
|
|
* Enumerate all the links in the listbox and change those starting
|
|
* with lpszFrom to lpszTo.
|
|
*
|
|
* Parameters:
|
|
* hListBox window handle of
|
|
* lpOleUILinkCntr pointer to OleUI Link Container
|
|
* lpszFrom prefix for matching
|
|
* lpszTo prefix to substitution
|
|
*
|
|
* Returns:
|
|
*/
|
|
VOID ChangeAllLinks(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo)
|
|
{
|
|
int cItems;
|
|
int nIndex;
|
|
int cFrom;
|
|
LPLINKINFO lpLI;
|
|
TCHAR szTmp[MAX_PATH];
|
|
BOOL bFound;
|
|
|
|
cFrom = lstrlen(lpszFrom);
|
|
|
|
cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L);
|
|
OleDbgAssert(cItems >= 0);
|
|
|
|
bFound = FALSE;
|
|
|
|
#ifdef _DEBUG
|
|
OleDbgPrint(3, TEXT("From : "), lpszFrom, 0);
|
|
OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0);
|
|
OleDbgPrint(3, TEXT("To : "), lpszTo, 0);
|
|
OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0);
|
|
#endif
|
|
|
|
for (nIndex = 0; nIndex < cItems; nIndex++)
|
|
{
|
|
lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, nIndex, 0);
|
|
|
|
// unmark the item
|
|
lpLI->fIsMarked = FALSE;
|
|
|
|
/* if the corresponding position for the end of lpszFrom in the
|
|
** display name is not a separator. We stop comparing this
|
|
** link.
|
|
*/
|
|
if (!*(lpLI->lpszDisplayName + cFrom) ||
|
|
(*(lpLI->lpszDisplayName + cFrom) == '\\') ||
|
|
(*(lpLI->lpszDisplayName + cFrom) == '!'))
|
|
{
|
|
lstrcpyn(szTmp, lpLI->lpszDisplayName, cFrom + 1);
|
|
if (!lstrcmp(szTmp, lpszFrom))
|
|
{
|
|
HRESULT hErr;
|
|
int nFileLength;
|
|
ULONG ulDummy;
|
|
|
|
if (!bFound)
|
|
{
|
|
TCHAR szTitle[256];
|
|
TCHAR szMsg[256];
|
|
TCHAR szBuf[256];
|
|
int uRet;
|
|
|
|
LoadString(_g_hOleStdResInst, IDS_CHANGESOURCE, szTitle,
|
|
sizeof(szTitle)/sizeof(TCHAR));
|
|
LoadString(_g_hOleStdResInst, IDS_CHANGEADDITIONALLINKS,
|
|
szMsg, sizeof(szMsg)/sizeof(TCHAR));
|
|
wsprintf(szBuf, szMsg, lpszFrom);
|
|
uRet = MessageBox(hListBox, szBuf, szTitle,
|
|
MB_ICONQUESTION | MB_YESNO);
|
|
if (uRet == IDYES)
|
|
bFound = TRUE;
|
|
else
|
|
return;
|
|
}
|
|
|
|
lstrcpy(szTmp, lpszTo);
|
|
lstrcat(szTmp, lpLI->lpszDisplayName + cFrom);
|
|
nFileLength = lstrlen(szTmp) -
|
|
(lpLI->lpszItemName ? lstrlen(lpLI->lpszItemName) : 0);
|
|
|
|
hErr = lpOleUILinkCntr->SetLinkSource(
|
|
lpLI->dwLink,
|
|
szTmp,
|
|
(ULONG)nFileLength,
|
|
(ULONG FAR*)&ulDummy,
|
|
TRUE
|
|
);
|
|
if (hErr != NOERROR)
|
|
{
|
|
lpOleUILinkCntr->SetLinkSource(
|
|
lpLI->dwLink,
|
|
szTmp,
|
|
(ULONG)nFileLength,
|
|
(ULONG FAR*)&ulDummy,
|
|
FALSE);
|
|
}
|
|
lpLI->fIsMarked = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* have to do the refreshing after processing all links, otherwise
|
|
** the item positions will change during the process as the
|
|
** listbox stores items in order
|
|
*/
|
|
if (bFound)
|
|
RefreshLinkLB(hListBox, lpOleUILinkCntr);
|
|
}
|
|
|
|
|
|
|
|
/* LoadLinkLB
|
|
* ----------
|
|
*
|
|
* Purpose:
|
|
* Enumerate all links from the Link Container and build up the Link
|
|
* ListBox
|
|
*
|
|
* Parameters:
|
|
* hListBox window handle of
|
|
* lpOleUILinkCntr pointer to OleUI Link Container
|
|
* lpszFrom prefix for matching
|
|
* lpszTo prefix to substitution
|
|
*
|
|
* Returns:
|
|
* number of link items loaded, -1 if error
|
|
*/
|
|
int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr)
|
|
{
|
|
DWORD dwLink = 0;
|
|
LPLINKINFO lpLI;
|
|
int nIndex;
|
|
int cLinks;
|
|
|
|
cLinks = 0;
|
|
|
|
while ((dwLink = lpOleUILinkCntr->GetNextLink(dwLink)) != 0)
|
|
{
|
|
lpLI = (LPLINKINFO)OleStdMalloc(sizeof(LINKINFO));
|
|
if (NULL == lpLI)
|
|
return -1;
|
|
|
|
lpLI->fIsMarked = FALSE;
|
|
lpLI->fIsSelected = FALSE;
|
|
lpLI->fDontFree = FALSE;
|
|
|
|
lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(TCHAR));
|
|
|
|
lpLI->dwLink = dwLink;
|
|
cLinks++;
|
|
if ((nIndex = AddLinkLBItem(hListBox,lpOleUILinkCntr,lpLI,TRUE)) < 0)
|
|
// can't load list box
|
|
return -1;
|
|
|
|
if (lpLI->fIsSelected)
|
|
SendMessage(hListBox, LB_SETSEL, TRUE, MAKELPARAM(nIndex, 0));
|
|
}
|
|
if (SendMessage(hListBox,LB_GETSELITEMS,(WPARAM)1,(LPARAM)(int FAR*)&nIndex))
|
|
SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, MAKELPARAM(TRUE, 0));
|
|
|
|
return cLinks;
|
|
}
|
|
|
|
/* RefreshLinkLB
|
|
* -------------
|
|
*
|
|
* Purpose:
|
|
* Enumerate all items in the links listbox and update those with
|
|
* fIsMarked set.
|
|
* Note that this is a time consuming routine as it keeps iterating
|
|
* all items in the listbox until all of them are unmarked.
|
|
*
|
|
* Parameters:
|
|
* hListBox window handle of listbox
|
|
* lpOleUILinkCntr pointer to OleUI Link Container
|
|
*
|
|
* Returns:
|
|
*
|
|
*/
|
|
VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr)
|
|
{
|
|
int cItems;
|
|
int nIndex;
|
|
LPLINKINFO lpLI;
|
|
BOOL bStop;
|
|
|
|
OleDbgAssert(hListBox);
|
|
|
|
cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L);
|
|
OleDbgAssert(cItems >= 0);
|
|
|
|
do
|
|
{
|
|
bStop = TRUE;
|
|
for (nIndex = 0; nIndex < cItems; nIndex++)
|
|
{
|
|
lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, nIndex, 0);
|
|
if (lpLI->fIsMarked)
|
|
{
|
|
lpLI->fIsMarked = FALSE;
|
|
lpLI->fDontFree = TRUE;
|
|
|
|
SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L);
|
|
nIndex=AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE);
|
|
if (lpLI->fIsSelected)
|
|
{
|
|
SendMessage(hListBox, LB_SETSEL, (WPARAM)TRUE,
|
|
MAKELPARAM(nIndex, 0));
|
|
SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex,
|
|
MAKELPARAM(TRUE, 0));
|
|
}
|
|
bStop = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
} while (!bStop);
|
|
}
|