2147 lines
65 KiB
C
2147 lines
65 KiB
C
/*
|
||
* links.c
|
||
*
|
||
* Implements the OleUIEditLinks function which invokes the complete
|
||
* Edit Links dialog.
|
||
*
|
||
* Copyright (c)1992 Microsoft Corporation, All Right Reserved
|
||
*/
|
||
|
||
#define STRICT 1
|
||
|
||
#include "ole2ui.h"
|
||
#include "common.h"
|
||
#include "edlinks.h"
|
||
#include "utility.h"
|
||
#include <commdlg.h>
|
||
#include <dlgs.h>
|
||
#include <stdlib.h>
|
||
|
||
OLEDBGDATA
|
||
|
||
/*
|
||
* 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)
|
||
{
|
||
UINT uRet;
|
||
HGLOBAL hMemDlg=NULL;
|
||
|
||
uRet=UStandardValidation((LPOLEUISTANDARD)lpEL, sizeof(OLEUIEDITLINKS)
|
||
, &hMemDlg);
|
||
|
||
if (OLEUI_SUCCESS!=uRet)
|
||
return uRet;
|
||
|
||
/*
|
||
* PERFORM ANY STRUCTURE-SPECIFIC VALIDATION HERE!
|
||
* ON FAILURE:
|
||
* {
|
||
* if (NULL!=hMemDlg)
|
||
* FreeResource(hMemDlg)
|
||
*
|
||
* return OLEUI_<ABBREV>ERR_<ERROR>
|
||
* }
|
||
*/
|
||
|
||
//Now that we've validated everything, we can invoke the dialog.
|
||
uRet=UStandardInvocation(EditLinksDialogProc, (LPOLEUISTANDARD)lpEL,
|
||
hMemDlg, MAKEINTRESOURCE(IDD_EDITLINKS));
|
||
|
||
/*
|
||
* IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE.
|
||
*/
|
||
|
||
|
||
return uRet;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* EditLinksDialogProc
|
||
*
|
||
* Purpose:
|
||
* Implements the OLE Edit Links dialog as invoked through the
|
||
* OleUIEditLinks function.
|
||
*
|
||
* Parameters:
|
||
* Standard
|
||
*
|
||
* Return Value:
|
||
* Standard
|
||
*/
|
||
|
||
BOOL CALLBACK EXPORT EditLinksDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
LPEDITLINKS lpEL = NULL;
|
||
BOOL fHook=FALSE;
|
||
UINT uRet=0;
|
||
HRESULT hErr;
|
||
static int nColPos[3];
|
||
|
||
//Declare Win16/Win32 compatible WM_COMMAND parameters.
|
||
COMMANDPARAMS(wID, wCode, hWndMsg);
|
||
|
||
//This will fail under WM_INITDIALOG, where we allocate it.
|
||
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) {
|
||
|
||
PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp, wParam, lParam);
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
|
||
//Process the temination message
|
||
if (iMsg==uMsgEndDialog) {
|
||
|
||
//Free any specific allocations before calling StandardCleanup
|
||
|
||
StandardCleanup(lpEL, hDlg);
|
||
|
||
EndDialog(hDlg, wParam);
|
||
return TRUE;
|
||
}
|
||
|
||
switch (iMsg) {
|
||
static int nHeightLine = -1;
|
||
static int nMaxCharWidth = -1;
|
||
|
||
case WM_INITDIALOG:
|
||
{
|
||
RECT rc;
|
||
int nStart;
|
||
|
||
/* calculate the column positions relative to the listbox */
|
||
GetWindowRect(GetDlgItem(hDlg, ID_EL_LINKSLISTBOX), (LPRECT)&rc);
|
||
nStart = rc.left;
|
||
GetWindowRect(GetDlgItem(hDlg, ID_EL_COL1), (LPRECT)&rc);
|
||
nColPos[0] = rc.left - nStart;
|
||
GetWindowRect(GetDlgItem(hDlg, ID_EL_COL2), (LPRECT)&rc);
|
||
nColPos[1] = rc.left - nStart;
|
||
GetWindowRect(GetDlgItem(hDlg, ID_EL_COL3), (LPRECT)&rc);
|
||
nColPos[2] = rc.left - nStart;
|
||
|
||
return FEditLinksInit(hDlg, wParam, lParam);
|
||
}
|
||
break;
|
||
|
||
case WM_MEASUREITEM:
|
||
{
|
||
LPMEASUREITEMSTRUCT lpMIS;
|
||
|
||
lpMIS = (LPMEASUREITEMSTRUCT)lParam;
|
||
|
||
if (nHeightLine == -1) {
|
||
HFONT hFont;
|
||
HDC hDC;
|
||
TEXTMETRIC tm;
|
||
|
||
/* Attempt to get font dialog. If that fails,
|
||
use system font
|
||
*/
|
||
|
||
hFont = (HANDLE)(UINT)SendMessage(hDlg, WM_GETFONT, 0, 0L);
|
||
|
||
if (hFont == NULL)
|
||
hFont = GetStockObject(SYSTEM_FONT);
|
||
|
||
hDC = GetDC(hDlg);
|
||
hFont = SelectObject(hDC, hFont);
|
||
|
||
GetTextMetrics(hDC, &tm);
|
||
nHeightLine = tm.tmHeight;
|
||
nMaxCharWidth = tm.tmMaxCharWidth;
|
||
|
||
ReleaseDC(hDlg, hDC);
|
||
}
|
||
|
||
lpMIS->itemHeight = nHeightLine;
|
||
}
|
||
break;
|
||
|
||
case WM_DRAWITEM:
|
||
{
|
||
LPDRAWITEMSTRUCT lpDIS;
|
||
COLORREF crText;
|
||
LPLINKINFO lpLI;
|
||
HBRUSH hbr;
|
||
int nOldBkMode;
|
||
TCHAR tsz[OLEUI_CCHPATHMAX];
|
||
LPTSTR lpsz;
|
||
RECT rcClip;
|
||
|
||
lpDIS = (LPDRAWITEMSTRUCT)lParam;
|
||
lpLI = (LPLINKINFO)lpDIS->itemData;
|
||
|
||
if ((int)lpDIS->itemID < 0)
|
||
break;
|
||
|
||
if ((ODA_DRAWENTIRE | ODA_SELECT) & lpDIS->itemAction) {
|
||
|
||
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);
|
||
|
||
nOldBkMode = SetBkMode(lpDIS->hDC, TRANSPARENT);
|
||
|
||
if (lpLI->lpszDisplayName) {
|
||
lstrcpy((LPTSTR)tsz, lpLI->lpszDisplayName);
|
||
lpsz = ChopText(
|
||
lpDIS->hwndItem,
|
||
nColPos[1] - nColPos[0]
|
||
- (nMaxCharWidth > 0 ? nMaxCharWidth : 5),
|
||
tsz
|
||
);
|
||
rcClip.left = lpDIS->rcItem.left + nColPos[0];
|
||
rcClip.top = lpDIS->rcItem.top;
|
||
rcClip.right = lpDIS->rcItem.left + nColPos[1]
|
||
- (nMaxCharWidth > 0 ? 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 + nColPos[1];
|
||
rcClip.top = lpDIS->rcItem.top;
|
||
rcClip.right = lpDIS->rcItem.left + nColPos[2]
|
||
- (nMaxCharWidth > 0 ? 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 + 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);
|
||
|
||
}
|
||
|
||
InitControls(hDlg, lpEL);
|
||
|
||
if (ODA_FOCUS & lpDIS->itemAction)
|
||
DrawFocusRect(lpDIS->hDC, &lpDIS->rcItem);
|
||
|
||
}
|
||
return TRUE;
|
||
|
||
|
||
case WM_DELETEITEM:
|
||
{
|
||
UINT idCtl;
|
||
LPDELETEITEMSTRUCT lpDIS;
|
||
LPLINKINFO lpLI;
|
||
|
||
lpDIS = (LPDELETEITEMSTRUCT)lParam;
|
||
idCtl = wParam;
|
||
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 ID_EL_CHANGESOURCE:
|
||
{
|
||
BOOL fRet = FALSE;
|
||
|
||
/* This will bring up the file open dlg with one
|
||
edit field containing the whole link name. The file part
|
||
will (eventually) be highlighted to indicate where the
|
||
file part is. We need to hook on OK here to be able to
|
||
send the changed string to the Parse function */
|
||
|
||
fRet = Container_ChangeSource(hDlg, lpEL);
|
||
if (!fRet)
|
||
PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
|
||
MB_ICONEXCLAMATION | MB_OK);
|
||
InitControls(hDlg, lpEL);
|
||
}
|
||
break;
|
||
|
||
case ID_EL_AUTOMATIC:
|
||
{
|
||
/* This is available for single or multi-select. There is
|
||
a flag in the structure that is set initially indicating
|
||
whether the link is auto or manual so that we need not
|
||
query the link each time we want to find out.
|
||
|
||
This command will make the link automatic if not already.
|
||
It will have no effect on links already set to auto.
|
||
*/
|
||
// turn the button ON
|
||
|
||
CheckDlgButton(hDlg, ID_EL_AUTOMATIC, 1);
|
||
CheckDlgButton(hDlg, ID_EL_MANUAL, 0);
|
||
|
||
hErr = Container_AutomaticManual(hDlg, TRUE, lpEL);
|
||
if (hErr != NOERROR)
|
||
PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
|
||
MB_ICONEXCLAMATION | MB_OK);
|
||
|
||
InitControls(hDlg, lpEL);
|
||
}
|
||
break;
|
||
|
||
case ID_EL_MANUAL:
|
||
{
|
||
/* Same rules apply here as they do to auto link.
|
||
Additional note - just because something is changed does
|
||
not mean that it updates at the moment. It simply
|
||
reflects what kind of updating it does while it lives in
|
||
the document.
|
||
*/
|
||
// turn the button ON
|
||
|
||
CheckDlgButton(hDlg, ID_EL_MANUAL, 1);
|
||
CheckDlgButton(hDlg, ID_EL_AUTOMATIC, 0);
|
||
|
||
hErr = Container_AutomaticManual(hDlg, FALSE, lpEL);
|
||
if (hErr != NOERROR)
|
||
PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
|
||
MB_ICONEXCLAMATION | MB_OK);
|
||
|
||
InitControls(hDlg, lpEL);
|
||
}
|
||
break;
|
||
|
||
case ID_EL_CANCELLINK:
|
||
{
|
||
/* This is Break Link now in the dlg. This sets the
|
||
moniker to null, thereby effectively breaking the link.
|
||
The object still has its data effective at the time of
|
||
breaking, but becomes a static object.
|
||
*****It will need to be deleted from the listbox
|
||
*/
|
||
|
||
CancelLink(hDlg,lpEL);
|
||
InitControls(hDlg, lpEL);
|
||
}
|
||
break;
|
||
|
||
case ID_EL_UPDATENOW:
|
||
{
|
||
/* This forces an immediate update of the selected
|
||
links. This will start the server etc, so this is a very
|
||
expensive operation.
|
||
*/
|
||
hErr = Container_UpdateNow(hDlg, lpEL);
|
||
InitControls(hDlg, lpEL);
|
||
}
|
||
break;
|
||
|
||
case ID_EL_OPENSOURCE:
|
||
{
|
||
/* This will only work on single selection. It makes no
|
||
sense to open multiple sources at the same time, since
|
||
the one opened will try to show itself and become the
|
||
primary operating target, so to speak. Button is greyed
|
||
if multi select.
|
||
|
||
Here we do not add the break because we want to exit the
|
||
dlg in this case.
|
||
*/
|
||
hErr = Container_OpenSource(hDlg, lpEL);
|
||
if (hErr != NOERROR) {
|
||
InitControls(hDlg, lpEL);
|
||
break; // don't close dialog
|
||
}
|
||
} // fall through
|
||
|
||
case ID_EL_CLOSE:
|
||
{
|
||
/* The user is finished with their editing - they now
|
||
return to their container document.
|
||
|
||
*/
|
||
SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
|
||
}
|
||
break;
|
||
|
||
case IDCANCEL:
|
||
{
|
||
/* This changes to CLOSE after the user does even ONE
|
||
thing in the dlg. Nothing can really effectively be undone.
|
||
*/
|
||
SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
|
||
}
|
||
break;
|
||
|
||
case ID_OLEUIHELP:
|
||
{
|
||
PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp
|
||
, (WPARAM)hDlg, MAKELPARAM(IDD_EDITLINKS, 0));
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
{
|
||
if (lpEL && iMsg == lpEL->nChgSrcHelpID) {
|
||
PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp,
|
||
(WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0));
|
||
}
|
||
}
|
||
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)
|
||
{
|
||
LPEDITLINKS lpEL;
|
||
LPOLEUIEDITLINKS lpOEL;
|
||
HFONT hFont;
|
||
BOOL fDlgItem = FALSE;
|
||
DWORD dwLink = 0;
|
||
ULONG cLinks;
|
||
LPOLEUILINKCONTAINER lpOleUILinkCntr;
|
||
int n;
|
||
HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
|
||
|
||
|
||
|
||
//1. Copy the structure at lParam into our instance memory.
|
||
lpEL = (LPEDITLINKS)LpvStandardInit(hDlg, sizeof(OLEUIEDITLINKS), TRUE,
|
||
&hFont);
|
||
|
||
//PvStandardInit send a termination to us already.
|
||
if (NULL==lpEL)
|
||
return FALSE;
|
||
|
||
lpOEL=(LPOLEUIEDITLINKS)lParam;
|
||
|
||
lpEL->lpOEL=lpOEL;
|
||
|
||
lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
||
|
||
cLinks = LoadLinkLB(hListBox, lpOleUILinkCntr);
|
||
if (cLinks < 0)
|
||
return FALSE;
|
||
|
||
fDlgItem = (BOOL)cLinks;
|
||
lpEL->fItemsExist = (BOOL)cLinks;
|
||
|
||
|
||
InitControls(hDlg, lpEL);
|
||
|
||
//Copy other information from lpOEL that we might modify.
|
||
|
||
//2. 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);
|
||
}
|
||
|
||
|
||
//3. Show or hide the help button
|
||
if (!(lpEL->lpOEL->dwFlags & ELF_SHOWHELP))
|
||
StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
|
||
|
||
/*
|
||
* PERFORM OTHER INITIALIZATION HERE. ON ANY LoadString
|
||
* FAILURE POST OLEUI_MSG_ENDDIALOG WITH OLEUI_ERR_LOADSTRING.
|
||
*/
|
||
|
||
//4. If requested disable UpdateNow button
|
||
if ((lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW))
|
||
StandardShowDlgItem(hDlg, ID_EL_UPDATENOW, SW_HIDE);
|
||
|
||
//5. If requested disable OpenSource button
|
||
if ((lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE))
|
||
StandardShowDlgItem(hDlg, ID_EL_OPENSOURCE, SW_HIDE);
|
||
|
||
//6. If requested disable UpdateNow button
|
||
if ((lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE))
|
||
StandardShowDlgItem(hDlg, ID_EL_CHANGESOURCE, SW_HIDE);
|
||
|
||
//7. If requested disable CancelLink button
|
||
if ((lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK))
|
||
StandardShowDlgItem(hDlg, ID_EL_CANCELLINK, SW_HIDE);
|
||
|
||
//8. Load 'Close' string used to rename Cancel button
|
||
n = LoadString(ghInst, 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);
|
||
|
||
//n. Call the hook with lCustData in lParam
|
||
UStandardHook(lpEL, hDlg, WM_INITDIALOG, wParam, lpOEL->lCustData);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* ChangeSourceHook
|
||
*
|
||
* Purpose:
|
||
* Hooks the ChangeSource dialog to attempt to validate link source changes
|
||
* specified by the user.
|
||
*
|
||
* Parameters:
|
||
* hDlg HWND of the dialog
|
||
* uMsg UINT Message
|
||
* wParam WPARAM of the message
|
||
* lParam LPARAM of the message
|
||
*
|
||
* Return Value:
|
||
* UNIT Zero = Do default processing;
|
||
* Non Zero = Don't do default processing.
|
||
*/
|
||
|
||
UINT CALLBACK EXPORT ChangeSourceHook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
LPCHANGESOURCEHOOKDATA lpCshData = NULL;
|
||
LPLINKINFO lpLI = NULL;
|
||
LPEDITLINKS lpEL = NULL;
|
||
LPOLEUILINKCONTAINER lpOleUILinkCntr;
|
||
HRESULT hErr;
|
||
UINT uRet;
|
||
ULONG ulChEaten;
|
||
HGLOBAL gh;
|
||
|
||
//This will fail under WM_INITDIALOG, where we allocate it.
|
||
if (NULL!=(gh = GetProp(hDlg, STRUCTUREPROP)))
|
||
{
|
||
// gh was locked previously, lock and unlock to get lpv
|
||
lpCshData=(LPCHANGESOURCEHOOKDATA)GlobalLock(gh);
|
||
GlobalUnlock(gh);
|
||
if (lpCshData)
|
||
{
|
||
lpLI = lpCshData->lpOCshData->lpLI;
|
||
lpEL = lpCshData->lpOCshData->lpEL;
|
||
}
|
||
}
|
||
|
||
//Process the temination message
|
||
if (uMsg==uMsgEndDialog)
|
||
{
|
||
if (NULL!=(gh = RemoveProp(hDlg, STRUCTUREPROP)))
|
||
{
|
||
GlobalUnlock(gh);
|
||
GlobalFree(gh);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
// User pressed the OK button
|
||
if (uMsg == uMsgFileOKString) {
|
||
lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
||
|
||
/* NOTE: trigger the focus lost of the edit control. This is
|
||
** not necessary if the user click OK with the mouse but is
|
||
** needed when the user just press <Enter>. If the mouse was
|
||
** used, no extra is done as the MODIFY flag of the edit control
|
||
** has been cleared.
|
||
*/
|
||
SendMessage(hDlg, WM_COMMAND, edt1,
|
||
MAKELPARAM(GetDlgItem(hDlg, edt1), EN_KILLFOCUS));
|
||
if (lpCshData->bItemNameStored) {
|
||
lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit) -
|
||
lstrlen((LPTSTR)lpCshData->szItemName);
|
||
}
|
||
else {
|
||
lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit);
|
||
}
|
||
|
||
// Try to validate link source change
|
||
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkSource called\r\n"));
|
||
hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource(
|
||
lpOleUILinkCntr,
|
||
lpLI->dwLink,
|
||
(LPTSTR)lpCshData->szEdit,
|
||
(ULONG)lpCshData->nFileLength,
|
||
&ulChEaten,
|
||
TRUE
|
||
);
|
||
OLEDBG_END2
|
||
|
||
// Link source change not validated
|
||
if (hErr != NOERROR) {
|
||
uRet =PopupMessage(hDlg, IDS_CHANGESOURCE, IDS_INVALIDSOURCE,
|
||
MB_ICONQUESTION | MB_YESNO);
|
||
|
||
if (uRet == IDYES) {
|
||
/* User wants to correct invalid link. Set the edit
|
||
** control selection to the invalid part of the contents.
|
||
*/
|
||
SetFocus(GetDlgItem(hDlg, edt1));
|
||
SendDlgItemMessage(hDlg, edt1, EM_SETSEL, 0,
|
||
MAKELPARAM(ulChEaten, -1));
|
||
return 1; // Don't close ChangeSource dialog
|
||
}
|
||
else {
|
||
/* User does not want to correct invalid link. So set
|
||
** the link source but don't validate the link.
|
||
*/
|
||
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkSource called\r\n"));
|
||
hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource(
|
||
lpOleUILinkCntr,
|
||
lpLI->dwLink,
|
||
(LPTSTR)lpCshData->szEdit,
|
||
(ULONG)lpCshData->nFileLength,
|
||
&ulChEaten,
|
||
FALSE
|
||
);
|
||
OLEDBG_END2
|
||
lpCshData->fValidLink = FALSE;
|
||
}
|
||
}
|
||
else { // Link source change validated
|
||
lpCshData->fValidLink = TRUE;
|
||
}
|
||
|
||
if (lpCshData->bItemNameStored && lpCshData->bFileNameStored) {
|
||
HWND hListBox = GetDlgItem(lpCshData->lpOfn->hwndOwner, ID_EL_LINKSLISTBOX);
|
||
|
||
DiffPrefix(
|
||
lpLI->lpszDisplayName,
|
||
(LPTSTR)lpCshData->szEdit,
|
||
(TCHAR FAR* FAR*)&lpCshData->lpszFrom,
|
||
(TCHAR FAR* FAR*)&lpCshData->lpszTo
|
||
);
|
||
|
||
/* we keep the strings if there is a difference between the
|
||
** lpszFrom and lpszTo strings AND if the change is only
|
||
** in the file portion otherwise free them and other
|
||
** links won't be compared.
|
||
*/
|
||
if ( (lstrcmp(lpCshData->lpszTo, lpCshData->lpszFrom)==0)
|
||
|| (lstrlen(lpCshData->lpszTo)>lpCshData->nFileLength)) {
|
||
if (lpCshData->lpszFrom) {
|
||
OleStdFree(lpCshData->lpszFrom);
|
||
lpCshData->lpszFrom = NULL;
|
||
}
|
||
if (lpCshData->lpszTo) {
|
||
OleStdFree(lpCshData->lpszTo);
|
||
lpCshData->lpszTo = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Copy OUT results to original structure
|
||
lpCshData->lpOCshData->lpszFrom = lpCshData->lpszFrom;
|
||
lpCshData->lpOCshData->lpszTo = lpCshData->lpszTo;
|
||
lpCshData->lpOCshData->fValidLink = lpCshData->fValidLink;
|
||
|
||
SendMessage(hDlg, uMsgEndDialog, 0, 0L); // do cleanup
|
||
return 0; // Close ChangeSource dialog
|
||
}
|
||
|
||
switch (uMsg) {
|
||
case WM_INITDIALOG:
|
||
{
|
||
LPOPENFILENAME lpOfn = (LPOPENFILENAME)lParam;
|
||
LPOLEUICHANGESOURCEHOOKDATA lpOCshData =
|
||
(LPOLEUICHANGESOURCEHOOKDATA)lpOfn->lCustData;
|
||
|
||
gh=GlobalAlloc(
|
||
GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(CHANGESOURCEHOOKDATA));
|
||
if (NULL==gh)
|
||
{
|
||
// Memory allocation error; fail to bring up dialog
|
||
PostMessage(hDlg, uMsgEndDialog, 0, 0L);
|
||
return 0;
|
||
}
|
||
lpCshData = GlobalLock(gh);
|
||
SetProp(hDlg, STRUCTUREPROP, gh);
|
||
|
||
lpCshData->lpOCshData = lpOCshData;
|
||
lpCshData->lpOfn = lpOfn;
|
||
lpLI = lpCshData->lpOCshData->lpLI;
|
||
|
||
lpCshData->bFileNameStored = TRUE;
|
||
lpCshData->bItemNameStored = TRUE;
|
||
lpCshData->nFileLength = (int)lpLI->clenFileName;
|
||
if (lpLI->lpszDisplayName) {
|
||
LSTRCPYN((LPTSTR)lpCshData->szFileName, lpLI->lpszDisplayName,
|
||
lpCshData->nFileLength + 1);
|
||
lstrcpy((LPTSTR)lpCshData->szEdit, lpLI->lpszDisplayName);
|
||
} else {
|
||
lpCshData->szFileName[0] = TEXT('\0');
|
||
lpCshData->szEdit[0] = TEXT('\0');
|
||
}
|
||
if (lpLI->lpszItemName)
|
||
lstrcpy((LPTSTR)lpCshData->szItemName, lpLI->lpszItemName);
|
||
else
|
||
lpCshData->szItemName[0] = TEXT('\0');
|
||
|
||
return 0;
|
||
}
|
||
|
||
case WM_COMMAND:
|
||
|
||
// User pressed the CANCEL button
|
||
if (wParam == IDCANCEL)
|
||
{
|
||
if (lpCshData->lpszFrom)
|
||
{
|
||
OleStdFree(lpCshData->lpszFrom);
|
||
lpCshData->lpszFrom = NULL;
|
||
}
|
||
if (lpCshData->lpszTo)
|
||
{
|
||
OleStdFree(lpCshData->lpszTo);
|
||
lpCshData->lpszTo = NULL;
|
||
}
|
||
|
||
// Copy OUT results to original structure
|
||
lpCshData->lpOCshData->lpszFrom = NULL;
|
||
lpCshData->lpOCshData->lpszTo = NULL;
|
||
lpCshData->lpOCshData->fValidLink = FALSE;
|
||
|
||
SendMessage(hDlg, uMsgEndDialog, 0, 0L); // do cleanup
|
||
return 0; // Close ChangeSource dialog
|
||
}
|
||
|
||
if ((wParam == lst1) &&
|
||
(HIWORD(lParam) == LBN_SELCHANGE)) {
|
||
|
||
int nIndex;
|
||
HWND hListBox = (HWND)LOWORD(lParam);
|
||
static TCHAR szFileNameBuf[OLEUI_CCHPATHMAX];
|
||
static TCHAR szEditBuf[OLEUI_CCHPATHMAX];
|
||
|
||
nIndex = (int)SendMessage(hListBox, LB_GETCURSEL, 0, 0L);
|
||
SendMessage(hListBox, LB_GETTEXT,
|
||
(WPARAM)nIndex, (LPARAM)(LPTSTR)szFileNameBuf);
|
||
|
||
/* need to build the full path filename for the moniker */
|
||
#ifdef WIN32
|
||
CharToOem(szFileNameBuf, szFileNameBuf);
|
||
#else
|
||
AnsiToOem(szFileNameBuf, szFileNameBuf);
|
||
#endif
|
||
_fullpath(szEditBuf, szFileNameBuf, sizeof(szEditBuf));
|
||
#ifdef WIN32
|
||
OemToChar(szEditBuf, szEditBuf);
|
||
#else
|
||
OemToAnsi(szEditBuf, szEditBuf);
|
||
#endif
|
||
|
||
/* convert filename to lower case as it appears in the
|
||
** listbox
|
||
*/
|
||
#ifdef WIN32
|
||
CharLower(szEditBuf);
|
||
#else
|
||
AnsiLower(szEditBuf);
|
||
#endif
|
||
LSTRCPYN((LPTSTR)lpCshData->szEdit, (LPTSTR)szEditBuf,
|
||
sizeof(lpCshData->szEdit) / sizeof(TCHAR));
|
||
LSTRCPYN((LPTSTR)lpCshData->szFileName,
|
||
(LPTSTR)lpCshData->szEdit,
|
||
sizeof(lpCshData->szFileName) / sizeof(TCHAR) );
|
||
lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit);
|
||
if (lpCshData->bItemNameStored)
|
||
lstrcat((LPTSTR)lpCshData->szEdit, lpCshData->szItemName);
|
||
|
||
SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szEdit);
|
||
lpCshData->nEditLength = lstrlen((LPTSTR)lpCshData->szEdit);
|
||
lpCshData->bFileNameStored = TRUE;
|
||
|
||
return 1;
|
||
}
|
||
|
||
if ((wParam == lst2) &&
|
||
(HIWORD(lParam) == LBN_SELCHANGE)) {
|
||
|
||
if (lpCshData->bItemNameStored)
|
||
SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szItemName);
|
||
|
||
return 1;
|
||
}
|
||
|
||
if ((wParam == cmb2) &&
|
||
(HIWORD(lParam) == CBN_SELCHANGE)) {
|
||
|
||
if (lpCshData->bItemNameStored)
|
||
SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szItemName);
|
||
|
||
return 1;
|
||
}
|
||
|
||
if (wParam == edt1) {
|
||
HWND hEdit = (HWND)LOWORD(lParam);
|
||
|
||
switch (HIWORD(lParam)) {
|
||
case EN_SETFOCUS:
|
||
SendMessage(hEdit, EM_SETSEL, 0,
|
||
MAKELPARAM(0, lpCshData->nFileLength));
|
||
return 1;
|
||
|
||
case EN_KILLFOCUS:
|
||
if (SendMessage(hEdit, EM_GETMODIFY, 0, 0L)) {
|
||
TCHAR szTmp[OLEUI_CCHPATHMAX];
|
||
int nItemLength = lstrlen((LPTSTR)lpCshData->szItemName);
|
||
|
||
*(LPWORD)lpCshData->szEdit = sizeof(lpCshData->szEdit)/
|
||
sizeof(TCHAR) - 1;
|
||
lpCshData->nEditLength = (int)SendMessage(hEdit,
|
||
EM_GETLINE, 0, (LPARAM)(LPTSTR)lpCshData->szEdit);
|
||
lpCshData->szEdit[lpCshData->nEditLength] = TEXT('\0');
|
||
LSTRCPYN((LPTSTR)szTmp, (LPTSTR)lpCshData->szEdit,
|
||
lpCshData->nFileLength + 1);
|
||
|
||
if (lpCshData->bFileNameStored &&
|
||
!lstrcmp((LPTSTR)lpCshData->szFileName, (LPTSTR)szTmp)) {
|
||
lstrcpy((LPTSTR)lpCshData->szItemName,
|
||
(LPTSTR)lpCshData->szEdit + lpCshData->nFileLength);
|
||
lpCshData->bItemNameStored = TRUE;
|
||
}
|
||
else if (lpCshData->bItemNameStored &&
|
||
!lstrcmp((LPTSTR)lpCshData->szItemName,
|
||
(LPTSTR)lpCshData->szEdit +
|
||
lpCshData->nEditLength -
|
||
nItemLength)) {
|
||
if (lpCshData->nEditLength==nItemLength) {
|
||
|
||
lpCshData->bFileNameStored = FALSE;
|
||
} else {
|
||
LSTRCPYN((LPTSTR)lpCshData->szFileName,
|
||
(LPTSTR)lpCshData->szEdit,
|
||
lpCshData->nEditLength -
|
||
nItemLength+1);
|
||
lpCshData->bFileNameStored = TRUE;
|
||
}
|
||
}
|
||
else {
|
||
lpCshData->bItemNameStored = FALSE;
|
||
lpCshData->bFileNameStored = FALSE;
|
||
}
|
||
|
||
SendMessage(hEdit, EM_SETMODIFY, FALSE, 0L);
|
||
}
|
||
return 0;
|
||
}
|
||
}
|
||
return 0;
|
||
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* ChangeSource
|
||
*
|
||
* Purpose:
|
||
* Displays the standard GetOpenFileName dialog with a customized template and
|
||
* hook.
|
||
*
|
||
* Parameters:
|
||
* hWndOwner HWND owning the dialog
|
||
* lpszFile LPSTR specifying the initial file. If there is no
|
||
* initial file the first character of this string should
|
||
* be a null.
|
||
* cchFile UINT length of pszFile
|
||
* iFilterString UINT index into the stringtable for the filter string.
|
||
* lpfnBrowseHook COMMDLGHOOKPROC hook to process link source information when user
|
||
* presses OK
|
||
* lpCshData LPCHANGESOURCEHOOKDATA custom data that is accessible to the hook
|
||
*
|
||
* Return Value:
|
||
* BOOL TRUE if the user selected a file and pressed OK.
|
||
* FALSE otherwise, such as on pressing Cancel.
|
||
*/
|
||
|
||
BOOL WINAPI ChangeSource(
|
||
HWND hWndOwner,
|
||
LPTSTR lpszFile,
|
||
UINT cchFile,
|
||
UINT iFilterString,
|
||
COMMDLGHOOKPROC lpfnBrowseHook,
|
||
LPOLEUICHANGESOURCEHOOKDATA lpCshData
|
||
)
|
||
{
|
||
UINT cch;
|
||
TCHAR szFilters[OLEUI_CCHPATHMAX];
|
||
TCHAR szDir[OLEUI_CCHPATHMAX];
|
||
TCHAR szTitle[OLEUI_CCHPATHMAX];
|
||
OPENFILENAME ofn;
|
||
BOOL fStatus;
|
||
LPTSTR lpszFileBuffer;
|
||
|
||
if (NULL==lpszFile || 0==cchFile)
|
||
return FALSE;
|
||
|
||
lpszFileBuffer = (LPTSTR)OleStdMalloc(cchFile * sizeof(TCHAR));
|
||
if (!lpszFileBuffer)
|
||
return FALSE;
|
||
|
||
lstrcpy(lpszFileBuffer, lpszFile);
|
||
|
||
// Get filters
|
||
if (0!=iFilterString)
|
||
cch = LoadString(ghInst, iFilterString, (LPTSTR)szFilters,
|
||
OLEUI_CCHPATHMAX);
|
||
else
|
||
{
|
||
szFilters[0]=0;
|
||
cch=1;
|
||
}
|
||
if (0==cch) {
|
||
fStatus = FALSE;
|
||
goto cleanup;
|
||
}
|
||
|
||
ReplaceCharWithNull(szFilters, szFilters[cch-1]);
|
||
|
||
LSTRCPYN((LPTSTR)szDir, lpszFile, OLEUI_CCHPATHMAX);
|
||
for (cch = lstrlen((LPTSTR)szDir) - 1; cch >= 0; cch--)
|
||
{
|
||
if ((szDir[cch]==TEXT('\\')) || (szDir[cch]==TEXT(':')) || (szDir[cch]==TEXT('/')))
|
||
break;
|
||
}
|
||
if (cch < 0)
|
||
cch = 0;
|
||
|
||
szDir[cch] = TEXT('\0');
|
||
|
||
LoadString(ghInst, IDS_CHANGESOURCE, (LPTSTR)szTitle, OLEUI_CCHPATHMAX);
|
||
_fmemset((LPOPENFILENAME)&ofn, 0, sizeof(ofn));
|
||
ofn.lStructSize = sizeof(ofn);
|
||
ofn.hwndOwner = hWndOwner;
|
||
ofn.lpstrFile = lpszFileBuffer;
|
||
ofn.nMaxFile = cchFile;
|
||
ofn.lpstrFilter = (LPTSTR)szFilters;
|
||
ofn.nFilterIndex = 1;
|
||
ofn.lpstrTitle = (LPTSTR)szTitle;
|
||
ofn.lpstrInitialDir = (LPTSTR)szDir;
|
||
ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEOPEN);
|
||
ofn.lpfnHook = lpfnBrowseHook;
|
||
ofn.hInstance = ghInst;
|
||
ofn.lCustData = (LPARAM)lpCshData;
|
||
ofn.Flags = OFN_NOVALIDATE | OFN_HIDEREADONLY |
|
||
OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
|
||
|
||
// Only show help button if edit links dialog shows it.
|
||
if (lpCshData->lpEL->lpOEL->dwFlags & ELF_SHOWHELP)
|
||
ofn.Flags |= OFN_SHOWHELP;
|
||
|
||
fStatus = GetOpenFileName((LPOPENFILENAME)&ofn);
|
||
|
||
cleanup:
|
||
OleStdFree((LPVOID)lpszFileBuffer);
|
||
return fStatus;
|
||
|
||
}
|
||
|
||
/*
|
||
* 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)
|
||
{
|
||
UINT uRet;
|
||
int cSelItems;
|
||
int FAR* rgIndex;
|
||
int i = 0;
|
||
LPLINKINFO lpLI;
|
||
HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
|
||
LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
||
OLEUICHANGESOURCEHOOKDATA cshData; // Data that needs to be accessed
|
||
// by the ChangeSource dialog hook
|
||
|
||
cSelItems = GetSelectedItems(hListBox, &rgIndex);
|
||
|
||
if (cSelItems < 0)
|
||
return FALSE;
|
||
|
||
if (!cSelItems)
|
||
return TRUE;
|
||
|
||
if (!lpEL->fClose) {
|
||
SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
|
||
lpEL->fClose = TRUE;
|
||
}
|
||
|
||
_fmemset((LPOLEUICHANGESOURCEHOOKDATA)&cshData, 0, sizeof(cshData));
|
||
cshData.cbStruct=sizeof(cshData);
|
||
cshData.hWndOwner=hDlg;
|
||
cshData.lpEL = (LPEDITLINKS)lpEL;
|
||
cshData.lpszFrom = NULL;
|
||
cshData.lpszTo = NULL;
|
||
|
||
for (i = cSelItems-1; i >=0; i--) {
|
||
SendMessage(hListBox, LB_GETTEXT, rgIndex[i],
|
||
(LPARAM) (LPLINKINFO FAR*) &lpLI);
|
||
|
||
uRet = UStandardHook(lpEL, hDlg, uMsgBrowse,
|
||
OLEUI_CCHPATHMAX_SIZE, (LONG)(LPTSTR)lpLI->lpszDisplayName);
|
||
|
||
if (!uRet) {
|
||
cshData.lpLI = lpLI;
|
||
/* Bring up the ChangeSource dialog after hooking it so
|
||
** that the user specified link source is verified
|
||
** when OK is pressed.
|
||
*/
|
||
uRet = (UINT)ChangeSource(hDlg, lpLI->lpszDisplayName,
|
||
OLEUI_CCHPATHMAX, IDS_FILTERS, ChangeSourceHook,
|
||
&cshData);
|
||
}
|
||
|
||
/* If Cancel is pressed in any ChangeSource dialog, stop
|
||
** the ChangeSource processing for all links.
|
||
*/
|
||
if (!uRet) {
|
||
if (rgIndex)
|
||
OleStdFree(rgIndex);
|
||
return TRUE;
|
||
}
|
||
|
||
UpdateLinkLBItem(hListBox, rgIndex[i], lpEL, TRUE);
|
||
|
||
if (cshData.lpszFrom && cshData.lpszTo) {
|
||
ChangeAllLinks(hListBox, lpOleUILinkCntr, cshData.lpszFrom,
|
||
cshData.lpszTo);
|
||
OleStdFree(cshData.lpszFrom);
|
||
OleStdFree(cshData.lpszTo);
|
||
}
|
||
|
||
} // end FOR
|
||
|
||
|
||
if (rgIndex)
|
||
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, ID_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;
|
||
|
||
if (!lpEL->fClose)
|
||
SetDlgItemText(hDlg, IDCANCEL, (LPTSTR)lpEL->szClose);
|
||
|
||
for (i = 0; i < cSelItems; i++) {
|
||
SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[i],
|
||
(LPARAM) (LPLINKINFO FAR*) &lpLI);
|
||
|
||
if (fAutoMan) { // If switching to AUTOMATIC
|
||
if (!lpLI->fIsAuto) { // Only change MANUAL links
|
||
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n"));
|
||
hErr=lpOleUILinkCntr->lpVtbl->SetLinkUpdateOptions(
|
||
lpOleUILinkCntr,
|
||
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->lpVtbl->SetLinkUpdateOptions(
|
||
lpOleUILinkCntr,
|
||
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);
|
||
|
||
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, ID_EL_LINKSLISTBOX);
|
||
BOOL bUpdate = FALSE;
|
||
|
||
OleDbgAssert(lpOleUILinkCntr);
|
||
|
||
lpmk = NULL;
|
||
|
||
cSelItems = GetSelectedItems(hListBox, &rgIndex);
|
||
|
||
if (cSelItems < 0)
|
||
return ResultFromScode(E_FAIL);
|
||
|
||
if (!cSelItems)
|
||
return NOERROR;
|
||
|
||
if (!lpEL->fClose) {
|
||
SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
|
||
lpEL->fClose = TRUE;
|
||
}
|
||
|
||
for (i = 0; i < cSelItems; i++) {
|
||
SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[i],
|
||
(LPARAM)(LPLINKINFO FAR*) &lpLI);
|
||
|
||
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::CancelLink called\r\n"));
|
||
hErr = lpOleUILinkCntr->lpVtbl->CancelLink(
|
||
lpOleUILinkCntr,
|
||
lpLI->dwLink
|
||
);
|
||
OLEDBG_END2
|
||
|
||
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);
|
||
|
||
}
|
||
|
||
if (bUpdate)
|
||
RefreshLinkLB(hListBox, lpOleUILinkCntr);
|
||
|
||
if (rgIndex)
|
||
OleStdFree((LPVOID)rgIndex);
|
||
|
||
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, ID_EL_LINKSLISTBOX);
|
||
BOOL bUpdate = FALSE;
|
||
|
||
OleDbgAssert(lpOleUILinkCntr);
|
||
|
||
cSelItems = GetSelectedItems(hListBox, &rgIndex);
|
||
|
||
if (cSelItems < 0)
|
||
return ResultFromScode(E_FAIL);
|
||
|
||
if (!cSelItems)
|
||
return NOERROR;
|
||
|
||
if (!lpEL->fClose) {
|
||
SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
|
||
lpEL->fClose = TRUE;
|
||
}
|
||
|
||
for (i = 0; i < cSelItems; i++) {
|
||
SendMessage(hListBox, LB_GETTEXT,
|
||
(WPARAM)rgIndex[i], (LPARAM)(LPLINKINFO FAR*)&lpLI);
|
||
|
||
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::UpdateLink called\r\n"));
|
||
hErr = lpOleUILinkCntr->lpVtbl->UpdateLink(
|
||
lpOleUILinkCntr,
|
||
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);
|
||
|
||
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, ID_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;
|
||
|
||
if (!lpEL->fClose) {
|
||
SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
|
||
lpEL->fClose = TRUE;
|
||
}
|
||
|
||
SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[0],
|
||
(LPARAM)(LPLINKINFO FAR*)&lpLI);
|
||
|
||
OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::OpenLinkSource called\r\n"));
|
||
hErr = lpOleUILinkCntr->lpVtbl->OpenLinkSource(
|
||
lpOleUILinkCntr,
|
||
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);
|
||
|
||
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->lpVtbl->GetLinkSource(
|
||
lpOleUILinkCntr,
|
||
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->lpVtbl->GetLinkUpdateOptions(
|
||
lpOleUILinkCntr,
|
||
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(ghInst, IDS_LINK_AUTO, lpLI->lpszAMX,
|
||
(int)OleStdGetSize((LPVOID)lpLI->lpszAMX));
|
||
}
|
||
else {
|
||
lpLI->fIsAuto = FALSE;
|
||
LoadString(ghInst, IDS_LINK_MANUAL, lpLI->lpszAMX,
|
||
(int)OleStdGetSize((LPVOID)lpLI->lpszAMX));
|
||
}
|
||
}
|
||
else
|
||
LoadString(ghInst, IDS_LINK_UNKNOWN, lpLI->lpszAMX,
|
||
(int)OleStdGetSize((LPVOID)lpLI->lpszAMX));
|
||
|
||
BreakString(lpLI);
|
||
|
||
nIndex = (int)SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0,
|
||
(LPARAM)(DWORD)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) {
|
||
#ifdef WIN32
|
||
// AnsiPrev is obsolete in Win32
|
||
lpsz = CharPrev(lpLI->lpszDisplayName, lpsz);
|
||
#else
|
||
lpsz = AnsiPrev(lpLI->lpszDisplayName, lpsz);
|
||
#endif
|
||
if ((*lpsz == TEXT('\\')) || (*lpsz == TEXT('/')) || (*lpsz == TEXT(':')))
|
||
break;
|
||
}
|
||
|
||
if (lpsz == lpLI->lpszDisplayName)
|
||
lpLI->lpszShortFileName = lpsz;
|
||
else
|
||
#ifdef WIN32
|
||
// AnsiNext is obsolete in Win32
|
||
lpLI->lpszShortFileName = CharNext(lpsz);
|
||
#else
|
||
lpLI->lpszShortFileName = AnsiNext(lpsz);
|
||
#endif
|
||
}
|
||
|
||
|
||
/* 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 = SendMessage(hListBox, LB_GETSELCOUNT, 0, 0L);
|
||
if (cSelItems < 0) // error
|
||
return (int)cSelItems;
|
||
|
||
if (!cSelItems)
|
||
return 0;
|
||
|
||
*lprgIndex = (int FAR*)OleStdMalloc((int)cSelItems * sizeof(int));
|
||
|
||
cCheckItems = 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[OLEUI_CCHPATHMAX];
|
||
LPTSTR lpsz;
|
||
|
||
|
||
hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
|
||
|
||
cSelItems = GetSelectedItems(hListBox, &rgIndex);
|
||
if (cSelItems < 0)
|
||
return;
|
||
|
||
EnableWindow(GetDlgItem(hDlg, ID_EL_AUTOMATIC), (BOOL)cSelItems);
|
||
EnableWindow(GetDlgItem(hDlg, ID_EL_MANUAL), (BOOL)cSelItems);
|
||
if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK))
|
||
EnableWindow(GetDlgItem(hDlg, ID_EL_CANCELLINK), (BOOL)cSelItems);
|
||
if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE))
|
||
EnableWindow(GetDlgItem(hDlg, ID_EL_OPENSOURCE), cSelItems == 1);
|
||
if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE))
|
||
EnableWindow(GetDlgItem(hDlg, ID_EL_CHANGESOURCE), cSelItems == 1);
|
||
if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW))
|
||
EnableWindow(GetDlgItem(hDlg, ID_EL_UPDATENOW), (BOOL)cSelItems);
|
||
|
||
for (i = 0; i < cSelItems; i++) {
|
||
SendDlgItemMessage(
|
||
hDlg,
|
||
ID_EL_LINKSLISTBOX,
|
||
LB_GETTEXT,
|
||
(WPARAM)rgIndex[i],
|
||
(LPARAM)(LPLINKINFO FAR*)&lpLI);
|
||
|
||
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, ID_EL_AUTOMATIC, cAuto && !cManual);
|
||
CheckDlgButton(hDlg, ID_EL_MANUAL, !cAuto && cManual);
|
||
|
||
/* fill full source in static text box
|
||
** below list
|
||
*/
|
||
if (!bSameSource || !lpszSource)
|
||
lpszSource = szNULL;
|
||
lstrcpy((LPTSTR)tsz, lpszSource);
|
||
lpsz = ChopText(GetDlgItem(hDlg, ID_EL_LINKSOURCE), 0, tsz);
|
||
SetDlgItemText(hDlg, ID_EL_LINKSOURCE, lpsz);
|
||
|
||
/* fill full link type name in static
|
||
** "type" text box
|
||
*/
|
||
if (!bSameType || !lpszType)
|
||
lpszType = szNULL;
|
||
SetDlgItemText(hDlg, ID_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;
|
||
DWORD dwErr;
|
||
LPOLEUILINKCONTAINER lpOleUILinkCntr;
|
||
|
||
if (!hListBox || (nIndex < 0) || !lpEL)
|
||
return;
|
||
|
||
lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
|
||
|
||
dwErr = SendMessage(hListBox, LB_GETTEXT, nIndex,
|
||
(LPARAM)(LPLINKINFO FAR*) &lpLI);
|
||
|
||
if ((dwErr == LB_ERR) || !lpLI)
|
||
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, (WPARAM)TRUE, MAKELPARAM(nIndex, 0));
|
||
SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, MAKELPARAM(TRUE, 0));
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/* DiffPrefix
|
||
* ----------
|
||
*
|
||
* Purpose:
|
||
* Compare (case-insensitive) two strings and return the prefixes of the
|
||
* the strings formed by removing the common suffix string from them.
|
||
* Integrity of tokens (directory name, filename and object names) are
|
||
* preserved. Note that the prefixes are converted to upper case
|
||
* characters.
|
||
*
|
||
* Parameters:
|
||
* lpsz1 string 1
|
||
* lpsz2 string 2
|
||
* lplpszPrefix1 prefix of string 1
|
||
* lplpszPrefix2 prefix of string 2
|
||
*
|
||
* Returns:
|
||
*
|
||
*/
|
||
VOID DiffPrefix(LPCTSTR lpsz1, LPCTSTR lpsz2, TCHAR FAR* FAR* lplpszPrefix1, TCHAR FAR* FAR* lplpszPrefix2)
|
||
{
|
||
LPTSTR lpstr1;
|
||
LPTSTR lpstr2;
|
||
|
||
OleDbgAssert(lpsz1 && lpsz2 && *lpsz1 && *lpsz2 && lplpszPrefix1 &&
|
||
lplpszPrefix2);
|
||
|
||
*lplpszPrefix1 = NULL;
|
||
*lplpszPrefix2 = NULL;
|
||
#ifdef WIN32
|
||
*lplpszPrefix1 = OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(TCHAR));
|
||
#else
|
||
*lplpszPrefix1 = OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(BYTE));
|
||
#endif
|
||
if (!*lplpszPrefix1)
|
||
return;
|
||
|
||
#ifdef WIN32
|
||
*lplpszPrefix2 = OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(TCHAR));
|
||
#else
|
||
*lplpszPrefix2 = OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(BYTE));
|
||
#endif
|
||
if (!*lplpszPrefix2) {
|
||
OleStdFree(*lplpszPrefix1);
|
||
*lplpszPrefix1 = NULL;
|
||
return;
|
||
}
|
||
|
||
lstrcpy(*lplpszPrefix1, lpsz1);
|
||
lstrcpy(*lplpszPrefix2, lpsz2);
|
||
// AnsiLower(*lplpszPrefix1);
|
||
// AnsiLower(*lplpszPrefix2);
|
||
|
||
lpstr1 = *lplpszPrefix1 + lstrlen(*lplpszPrefix1);
|
||
lpstr2 = *lplpszPrefix2 + lstrlen(*lplpszPrefix2);
|
||
|
||
while ((lpstr1>*lplpszPrefix1) && (lpstr2>*lplpszPrefix2)) {
|
||
#ifdef WIN32
|
||
lpstr1 = CharPrev(*lplpszPrefix1, lpstr1);
|
||
lpstr2 = CharPrev(*lplpszPrefix2, lpstr2);
|
||
#else
|
||
lpstr1 = AnsiPrev(*lplpszPrefix1, lpstr1);
|
||
lpstr2 = AnsiPrev(*lplpszPrefix2, lpstr2);
|
||
#endif
|
||
if (*lpstr1 != *lpstr2) {
|
||
#ifdef WIN32
|
||
// AnsiNext is obsolete in Win32
|
||
lpstr1 = CharNext(lpstr1);
|
||
lpstr2 = CharNext(lpstr2);
|
||
#else
|
||
lpstr1 = AnsiNext(lpstr1);
|
||
lpstr2 = AnsiNext(lpstr2);
|
||
#endif
|
||
break;
|
||
}
|
||
}
|
||
|
||
for (; *lpstr1 && *lpstr1!=TEXT('\\') && *lpstr1!=TEXT('!');
|
||
#ifdef WIN32
|
||
lpstr1=CharNext(lpstr1));
|
||
#else
|
||
lpstr1=AnsiNext(lpstr1));
|
||
#endif
|
||
for (; *lpstr2 && *lpstr2!=TEXT('\\') && *lpstr2!=TEXT('!');
|
||
#ifdef WIN32
|
||
lpstr2=CharNext(lpstr2));
|
||
#else
|
||
lpstr2=AnsiNext(lpstr2));
|
||
#endif
|
||
|
||
*lpstr1 = TEXT('\0');
|
||
*lpstr2 = TEXT('\0');
|
||
}
|
||
|
||
|
||
/* PopupMessage
|
||
* ------------
|
||
*
|
||
* Purpose:
|
||
* Popup s messagebox and get some response from the user. It is the same
|
||
* as MessageBox() except that the title and message string are loaded
|
||
* from the resource file.
|
||
*
|
||
* Parameters:
|
||
* hwndParent parent window of message box
|
||
* idTitle id of title string
|
||
* idMessage id of message string
|
||
* fuStyle style of message box
|
||
*/
|
||
int PopupMessage(HWND hwndParent, UINT idTitle, UINT idMessage, UINT fuStyle)
|
||
{
|
||
TCHAR szTitle[256];
|
||
TCHAR szMsg[256];
|
||
|
||
LoadString(ghInst, idTitle, (LPTSTR)szTitle, sizeof(szTitle)/sizeof(TCHAR));
|
||
LoadString(ghInst, idMessage, (LPTSTR)szMsg, sizeof(szMsg)/sizeof(TCHAR));
|
||
return MessageBox(hwndParent, szMsg, szTitle, fuStyle);
|
||
}
|
||
|
||
|
||
/* 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;
|
||
LPTSTR szTmp[OLEUI_CCHPATHMAX];
|
||
BOOL bFound;
|
||
|
||
cFrom = lstrlen(lpszFrom);
|
||
|
||
cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L);
|
||
OleDbgAssert(cItems >= 0);
|
||
|
||
bFound = FALSE;
|
||
|
||
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);
|
||
|
||
for (nIndex=0; nIndex<cItems; nIndex++) {
|
||
SendMessage(hListBox, LB_GETTEXT, nIndex,
|
||
(LPARAM)(LPLINKINFO FAR*)&lpLI);
|
||
|
||
// 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) == TEXT('\\')) ||
|
||
(*(lpLI->lpszDisplayName + cFrom) == TEXT('!'))) {
|
||
|
||
LSTRCPYN((LPTSTR)szTmp, lpLI->lpszDisplayName, cFrom + 1);
|
||
if (!lstrcmp((LPTSTR)szTmp, lpszFrom)) {
|
||
HRESULT hErr;
|
||
int nFileLength;
|
||
ULONG ulDummy;
|
||
|
||
if (!bFound) {
|
||
TCHAR szTitle[256];
|
||
TCHAR szMsg[256];
|
||
TCHAR szBuf[256];
|
||
int uRet;
|
||
|
||
LoadString(ghInst, IDS_CHANGESOURCE, (LPTSTR)szTitle,
|
||
sizeof(szTitle)/sizeof(TCHAR));
|
||
LoadString(ghInst, IDS_CHANGEADDITIONALLINKS,
|
||
(LPTSTR)szMsg, sizeof(szMsg)/sizeof(TCHAR));
|
||
wsprintf((LPTSTR)szBuf, (LPTSTR)szMsg, lpszFrom);
|
||
uRet = MessageBox(hListBox, (LPTSTR)szBuf, (LPTSTR)szTitle,
|
||
MB_ICONQUESTION | MB_YESNO);
|
||
if (uRet == IDYES)
|
||
bFound = TRUE;
|
||
else
|
||
return; // exit function
|
||
}
|
||
|
||
lstrcpy((LPTSTR)szTmp, lpszTo);
|
||
lstrcat((LPTSTR)szTmp, lpLI->lpszDisplayName + cFrom);
|
||
nFileLength = lstrlen((LPTSTR)szTmp) -
|
||
(lpLI->lpszItemName ? lstrlen(lpLI->lpszItemName) : 0);
|
||
|
||
|
||
hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource(
|
||
lpOleUILinkCntr,
|
||
lpLI->dwLink,
|
||
(LPTSTR)szTmp,
|
||
(ULONG)nFileLength,
|
||
(ULONG FAR*)&ulDummy,
|
||
TRUE
|
||
);
|
||
if (hErr != NOERROR)
|
||
lpOleUILinkCntr->lpVtbl->SetLinkSource(
|
||
lpOleUILinkCntr,
|
||
lpLI->dwLink,
|
||
(LPTSTR)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->lpVtbl->GetNextLink(lpOleUILinkCntr,
|
||
dwLink)) != 0) {
|
||
lpLI = (LPLINKINFO)OleStdMalloc(sizeof(LINKINFO));
|
||
if (NULL == lpLI)
|
||
return -1;
|
||
|
||
lpLI->fIsMarked = FALSE;
|
||
lpLI->fIsSelected = FALSE;
|
||
lpLI->fDontFree = FALSE;
|
||
|
||
#ifdef WIN32
|
||
lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(TCHAR));
|
||
#else
|
||
lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(BYTE));
|
||
#endif
|
||
|
||
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++) {
|
||
SendMessage(hListBox, LB_GETTEXT, nIndex,
|
||
(LPARAM)(LPLINKINFO FAR*)&lpLI);
|
||
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);
|
||
}
|
||
|
||
|