Source code of Windows XP (NT5)
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

  1. /*
  2. * links.c
  3. *
  4. * Implements the OleUIEditLinks function which invokes the complete
  5. * Edit Links dialog.
  6. *
  7. * Copyright (c)1992 Microsoft Corporation, All Right Reserved
  8. */
  9. #include "precomp.h"
  10. #include "common.h"
  11. #include "utility.h"
  12. #include <commdlg.h>
  13. #include <dlgs.h>
  14. #include <stdlib.h>
  15. OLEDBGDATA
  16. // INTERNAL INFORMATION STARTS HERE
  17. #define OLEUI_SZMAX 255
  18. #define LINKTYPELEN 30 // was 9, now I've more than tripled it
  19. #define szNULL TEXT("\0")
  20. typedef UINT (CALLBACK* COMMDLGHOOKPROC)(HWND, UINT, WPARAM, LPARAM);
  21. // Internally used structure
  22. typedef struct tagLINKINFO
  23. {
  24. DWORD dwLink; // app specific identifier of a link
  25. LPTSTR lpszDisplayName; // file based part of name
  26. LPTSTR lpszItemName; // object part of name
  27. LPTSTR lpszShortFileName; // filename without path
  28. LPTSTR lpszShortLinkType; // Short link type - progID
  29. LPTSTR lpszFullLinkType; // Full link type - user friendly name
  30. LPTSTR lpszAMX; // Is the link auto (A) man (M) or dead (X)
  31. ULONG clenFileName; // count of file part of mon.
  32. BOOL fSourceAvailable; // bound or not - on boot assume yes??
  33. BOOL fIsAuto; // 1 =automatic, 0=manual update
  34. BOOL fIsMarked; // 1 = marked, 0 = not
  35. BOOL fDontFree; // Don't free this data since it's being reused
  36. BOOL fIsSelected; // item selected or to be selected
  37. } LINKINFO, FAR* LPLINKINFO;
  38. typedef struct tagEDITLINKS
  39. {
  40. // Keep this item first as the Standard* functions depend on it here.
  41. LPOLEUIEDITLINKS lpOEL; // Original structure passed.
  42. UINT nIDD; // IDD of dialog (used for help info)
  43. BOOL fClose; // Does the button read cancel (0) or
  44. // close (1)?
  45. BOOL fItemsExist; // TRUE, items in lbox, FALSE, none
  46. UINT nChgSrcHelpID; // ID for Help callback from ChangeSrc dlg
  47. TCHAR szClose[50]; // Text for Close button
  48. // (when Cancel button gets renamed)
  49. int nColPos[3]; // tab positions for list box
  50. int nHeightLine; // height of each line in owner draw listbox
  51. int nMaxCharWidth; // maximim width of text in owner draw listbox
  52. } EDITLINKS, *PEDITLINKS, FAR *LPEDITLINKS;
  53. // Internal function prototypes
  54. // LINKS.CPP
  55. INT_PTR CALLBACK EditLinksDialogProc(HWND, UINT, WPARAM, LPARAM);
  56. BOOL FEditLinksInit(HWND, WPARAM, LPARAM);
  57. BOOL Container_ChangeSource(HWND, LPEDITLINKS);
  58. HRESULT Container_AutomaticManual(HWND, BOOL, LPEDITLINKS);
  59. HRESULT CancelLink(HWND, LPEDITLINKS);
  60. HRESULT Container_UpdateNow(HWND, LPEDITLINKS);
  61. HRESULT Container_OpenSource(HWND, LPEDITLINKS);
  62. int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI,
  63. BOOL fGetSelected);
  64. VOID BreakString(LPLINKINFO);
  65. int GetSelectedItems(HWND, int FAR* FAR*);
  66. VOID InitControls(HWND hDlg, LPEDITLINKS lpEL);
  67. VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect);
  68. VOID ChangeAllLinks(HWND hLIstBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo);
  69. int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr);
  70. VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr);
  71. /*
  72. * OleUIEditLinks
  73. *
  74. * Purpose:
  75. * Invokes the standard OLE Edit Links dialog box allowing the user
  76. * to manipulate ole links (delete, update, change source, etc).
  77. *
  78. * Parameters:
  79. * lpEL LPOLEUIEditLinks pointing to the in-out structure
  80. * for this dialog.
  81. *
  82. * Return Value:
  83. * UINT One of the following codes, indicating success or error:
  84. * OLEUI_SUCCESS Success
  85. * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong
  86. */
  87. STDAPI_(UINT) OleUIEditLinks(LPOLEUIEDITLINKS lpEL)
  88. {
  89. HGLOBAL hMemDlg = NULL;
  90. UINT uRet = UStandardValidation((LPOLEUISTANDARD)lpEL, sizeof(OLEUIEDITLINKS),
  91. &hMemDlg);
  92. if (OLEUI_SUCCESS != uRet)
  93. return uRet;
  94. // Validate interface.
  95. if (NULL == lpEL->lpOleUILinkContainer)
  96. {
  97. uRet = OLEUI_ELERR_LINKCNTRNULL;
  98. }
  99. else if(IsBadReadPtr(lpEL->lpOleUILinkContainer, sizeof(IOleUILinkContainer)))
  100. {
  101. uRet = OLEUI_ELERR_LINKCNTRINVALID;
  102. }
  103. if (OLEUI_SUCCESS != uRet)
  104. {
  105. return(uRet);
  106. }
  107. UINT nIDD = bWin4 ? IDD_EDITLINKS4 : IDD_EDITLINKS;
  108. // Now that we've validated everything, we can invoke the dialog.
  109. uRet = UStandardInvocation(EditLinksDialogProc, (LPOLEUISTANDARD)lpEL,
  110. hMemDlg, MAKEINTRESOURCE(nIDD));
  111. return uRet;
  112. }
  113. /*
  114. * EditLinksDialogProc
  115. *
  116. * Purpose:
  117. * Implements the OLE Edit Links dialog as invoked through the
  118. * OleUIEditLinks function.
  119. *
  120. * Parameters:
  121. * Standard
  122. *
  123. * Return Value:
  124. * Standard
  125. */
  126. INT_PTR CALLBACK EditLinksDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  127. {
  128. // Declare Win16/Win32 compatible WM_COMMAND parameters.
  129. COMMANDPARAMS(wID, wCode, hWndMsg);
  130. // This will fail under WM_INITDIALOG, where we allocate it.
  131. UINT uRet = 0;
  132. LPEDITLINKS lpEL = (LPEDITLINKS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
  133. // If the hook processed the message, we're done.
  134. if (0 != uRet)
  135. return (BOOL)uRet;
  136. //Process help message from secondary dialog
  137. if ((iMsg == uMsgHelp) && (lpEL))
  138. {
  139. PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp, wParam, lParam);
  140. return FALSE;
  141. }
  142. // Process the temination message
  143. if (iMsg == uMsgEndDialog)
  144. {
  145. EndDialog(hDlg, wParam);
  146. return TRUE;
  147. }
  148. switch (iMsg)
  149. {
  150. case WM_DESTROY:
  151. if (lpEL)
  152. {
  153. StandardCleanup(lpEL, hDlg);
  154. }
  155. break;
  156. case WM_INITDIALOG:
  157. return FEditLinksInit(hDlg, wParam, lParam);
  158. case WM_MEASUREITEM:
  159. {
  160. LPMEASUREITEMSTRUCT lpMIS = (LPMEASUREITEMSTRUCT)lParam;
  161. int nHeightLine;
  162. if (lpEL && lpEL->nHeightLine != -1)
  163. {
  164. // use cached height
  165. nHeightLine = lpEL->nHeightLine;
  166. }
  167. else
  168. {
  169. HFONT hFont;
  170. HDC hDC;
  171. TEXTMETRIC tm;
  172. hFont = (HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0L);
  173. if (hFont == NULL)
  174. hFont = (HFONT)GetStockObject(SYSTEM_FONT);
  175. hDC = GetDC(hDlg);
  176. hFont = (HFONT)SelectObject(hDC, hFont);
  177. GetTextMetrics(hDC, &tm);
  178. nHeightLine = tm.tmHeight;
  179. if (lpEL)
  180. {
  181. lpEL->nHeightLine = nHeightLine;
  182. lpEL->nMaxCharWidth = tm.tmMaxCharWidth;
  183. }
  184. ReleaseDC(hDlg, hDC);
  185. }
  186. lpMIS->itemHeight = nHeightLine;
  187. }
  188. break;
  189. case WM_DRAWITEM:
  190. {
  191. LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
  192. LPLINKINFO lpLI = (LPLINKINFO)lpDIS->itemData;
  193. if ((int)lpDIS->itemID < 0)
  194. break;
  195. if ((ODA_DRAWENTIRE | ODA_SELECT) & lpDIS->itemAction)
  196. {
  197. HBRUSH hbr;
  198. COLORREF crText;
  199. if (ODS_SELECTED & lpDIS->itemState)
  200. {
  201. /*Get proper txt colors */
  202. crText = SetTextColor(lpDIS->hDC,
  203. GetSysColor(COLOR_HIGHLIGHTTEXT));
  204. hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  205. lpLI->fIsSelected = TRUE;
  206. }
  207. else
  208. {
  209. hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  210. lpLI->fIsSelected = FALSE;
  211. }
  212. FillRect(lpDIS->hDC, &lpDIS->rcItem, hbr);
  213. DeleteObject(hbr);
  214. int nOldBkMode = SetBkMode(lpDIS->hDC, TRANSPARENT);
  215. RECT rcClip;
  216. if (lpLI->lpszDisplayName)
  217. {
  218. TCHAR szTemp[MAX_PATH];
  219. lstrcpy(szTemp, lpLI->lpszDisplayName);
  220. LPTSTR lpsz = ChopText(
  221. lpDIS->hwndItem,
  222. lpEL->nColPos[1] - lpEL->nColPos[0]
  223. - (lpEL->nMaxCharWidth > 0 ?
  224. lpEL->nMaxCharWidth : 5),
  225. szTemp, 0
  226. );
  227. rcClip.left = lpDIS->rcItem.left + lpEL->nColPos[0];
  228. rcClip.top = lpDIS->rcItem.top;
  229. rcClip.right = lpDIS->rcItem.left + lpEL->nColPos[1]
  230. - (lpEL->nMaxCharWidth > 0 ?
  231. lpEL->nMaxCharWidth : 5);
  232. rcClip.bottom = lpDIS->rcItem.bottom;
  233. ExtTextOut(
  234. lpDIS->hDC,
  235. rcClip.left,
  236. rcClip.top,
  237. ETO_CLIPPED,
  238. (LPRECT)&rcClip,
  239. lpsz,
  240. lstrlen(lpsz),
  241. NULL
  242. );
  243. }
  244. if (lpLI->lpszShortLinkType)
  245. {
  246. rcClip.left = lpDIS->rcItem.left + lpEL->nColPos[1];
  247. rcClip.top = lpDIS->rcItem.top;
  248. rcClip.right = lpDIS->rcItem.left + lpEL->nColPos[2]
  249. - (lpEL->nMaxCharWidth > 0 ?
  250. lpEL->nMaxCharWidth : 5);
  251. rcClip.bottom = lpDIS->rcItem.bottom;
  252. ExtTextOut(
  253. lpDIS->hDC,
  254. rcClip.left,
  255. rcClip.top,
  256. ETO_CLIPPED,
  257. (LPRECT)&rcClip,
  258. lpLI->lpszShortLinkType,
  259. lstrlen(lpLI->lpszShortLinkType),
  260. NULL
  261. );
  262. }
  263. if (lpLI->lpszAMX)
  264. {
  265. rcClip.left = lpDIS->rcItem.left + lpEL->nColPos[2];
  266. rcClip.top = lpDIS->rcItem.top;
  267. rcClip.right = lpDIS->rcItem.right;
  268. rcClip.bottom = lpDIS->rcItem.bottom;
  269. ExtTextOut(
  270. lpDIS->hDC,
  271. rcClip.left,
  272. rcClip.top,
  273. ETO_CLIPPED,
  274. (LPRECT)&rcClip,
  275. lpLI->lpszAMX,
  276. lstrlen(lpLI->lpszAMX),
  277. NULL
  278. );
  279. }
  280. SetBkMode(lpDIS->hDC, nOldBkMode);
  281. // restore orig colors if we changed them
  282. if (ODS_SELECTED & lpDIS->itemState)
  283. SetTextColor(lpDIS->hDC, crText);
  284. }
  285. if (ODA_FOCUS & lpDIS->itemAction)
  286. DrawFocusRect(lpDIS->hDC, &lpDIS->rcItem);
  287. }
  288. return TRUE;
  289. case WM_DELETEITEM:
  290. {
  291. LPDELETEITEMSTRUCT lpDIS = (LPDELETEITEMSTRUCT)lParam;
  292. UINT idCtl = (UINT)wParam;
  293. LPLINKINFO lpLI = (LPLINKINFO)lpDIS->itemData;
  294. if (lpLI->lpszDisplayName)
  295. OleStdFree((LPVOID)lpLI->lpszDisplayName);
  296. if (lpLI->lpszShortLinkType)
  297. OleStdFree((LPVOID)lpLI->lpszShortLinkType);
  298. if (lpLI->lpszFullLinkType)
  299. OleStdFree((LPVOID)lpLI->lpszFullLinkType);
  300. /* The ChangeSource processing reuses allocated space for
  301. ** links that have been modified.
  302. */
  303. // Don't free the LINKINFO for the changed links
  304. if (lpLI->fDontFree)
  305. lpLI->fDontFree = FALSE;
  306. else
  307. {
  308. if (lpLI->lpszAMX)
  309. OleStdFree((LPVOID)lpLI->lpszAMX);
  310. OleStdFree((LPVOID)lpLI);
  311. }
  312. }
  313. return TRUE;
  314. case WM_COMPAREITEM:
  315. {
  316. LPCOMPAREITEMSTRUCT lpCIS = (LPCOMPAREITEMSTRUCT)lParam;
  317. LPLINKINFO lpLI1 = (LPLINKINFO)lpCIS->itemData1;
  318. LPLINKINFO lpLI2 = (LPLINKINFO)lpCIS->itemData2;
  319. // Sort list entries by DisplayName
  320. return lstrcmp(lpLI1->lpszDisplayName, lpLI2->lpszDisplayName);
  321. }
  322. case WM_COMMAND:
  323. switch (wID)
  324. {
  325. case IDC_EL_CHANGESOURCE:
  326. {
  327. BOOL fRet = Container_ChangeSource(hDlg, lpEL);
  328. if (!fRet)
  329. PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
  330. MB_ICONEXCLAMATION | MB_OK);
  331. InitControls(hDlg, lpEL);
  332. }
  333. break;
  334. case IDC_EL_AUTOMATIC:
  335. {
  336. CheckDlgButton(hDlg, IDC_EL_AUTOMATIC, 1);
  337. CheckDlgButton(hDlg, IDC_EL_MANUAL, 0);
  338. HRESULT hErr = Container_AutomaticManual(hDlg, TRUE, lpEL);
  339. if (hErr != NOERROR)
  340. PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
  341. MB_ICONEXCLAMATION | MB_OK);
  342. InitControls(hDlg, lpEL);
  343. }
  344. break;
  345. case IDC_EL_MANUAL:
  346. {
  347. CheckDlgButton(hDlg, IDC_EL_MANUAL, 1);
  348. CheckDlgButton(hDlg, IDC_EL_AUTOMATIC, 0);
  349. HRESULT hErr = Container_AutomaticManual(hDlg, FALSE, lpEL);
  350. if (hErr != NOERROR)
  351. PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
  352. MB_ICONEXCLAMATION | MB_OK);
  353. InitControls(hDlg, lpEL);
  354. }
  355. break;
  356. case IDC_EL_CANCELLINK:
  357. CancelLink(hDlg,lpEL);
  358. InitControls(hDlg, lpEL);
  359. break;
  360. case IDC_EL_UPDATENOW:
  361. Container_UpdateNow(hDlg, lpEL);
  362. InitControls(hDlg, lpEL);
  363. break;
  364. case IDC_EL_OPENSOURCE:
  365. {
  366. HRESULT hErr = Container_OpenSource(hDlg, lpEL);
  367. if (hErr != NOERROR)
  368. {
  369. InitControls(hDlg, lpEL);
  370. // Don't close dialog
  371. break;
  372. }
  373. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  374. } // fall through
  375. case IDC_EL_LINKSLISTBOX:
  376. if (wCode == LBN_SELCHANGE)
  377. InitControls(hDlg, lpEL);
  378. break;
  379. case IDCANCEL:
  380. SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
  381. break;
  382. case IDC_OLEUIHELP:
  383. PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp,
  384. (WPARAM)hDlg, MAKELPARAM(IDD_EDITLINKS, 0));
  385. break;
  386. }
  387. break;
  388. default:
  389. if (lpEL != NULL && iMsg == lpEL->nChgSrcHelpID)
  390. {
  391. PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp,
  392. (WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0));
  393. }
  394. if (iMsg == uMsgBrowseOFN &&
  395. lpEL != NULL && lpEL->lpOEL && lpEL->lpOEL->hWndOwner)
  396. {
  397. SendMessage(lpEL->lpOEL->hWndOwner, uMsgBrowseOFN, wParam, lParam);
  398. }
  399. break;
  400. }
  401. return FALSE;
  402. }
  403. /*
  404. * FEditLinksInit
  405. *
  406. * Purpose:
  407. * WM_INITIDIALOG handler for the Edit Links dialog box.
  408. *
  409. *
  410. * Parameters:
  411. * hDlg HWND of the dialog
  412. * wParam WPARAM of the message
  413. * lParam LPARAM of the message
  414. *
  415. * Return Value:
  416. * BOOL Value to return for WM_INITDIALOG.
  417. */
  418. BOOL FEditLinksInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
  419. {
  420. // Copy the structure at lParam into our instance memory.
  421. HFONT hFont;
  422. LPEDITLINKS lpEL = (LPEDITLINKS)LpvStandardInit(hDlg, sizeof(EDITLINKS), &hFont);
  423. // PvStandardInit send a termination to us already.
  424. if (NULL == lpEL)
  425. return FALSE;
  426. LPOLEUIEDITLINKS lpOEL = (LPOLEUIEDITLINKS)lParam;
  427. lpEL->lpOEL = lpOEL;
  428. lpEL->nIDD = IDD_EDITLINKS;
  429. // metrics unknown so far
  430. lpEL->nHeightLine = -1;
  431. lpEL->nMaxCharWidth = -1;
  432. /* calculate the column positions relative to the listbox */
  433. HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
  434. RECT rc;
  435. GetWindowRect(hListBox, (LPRECT)&rc);
  436. int nStart = rc.left;
  437. GetWindowRect(GetDlgItem(hDlg, IDC_EL_COL1), (LPRECT)&rc);
  438. lpEL->nColPos[0] = rc.left - nStart;
  439. GetWindowRect(GetDlgItem(hDlg, IDC_EL_COL2), (LPRECT)&rc);
  440. lpEL->nColPos[1] = rc.left - nStart;
  441. GetWindowRect(GetDlgItem(hDlg, IDC_EL_COL3), (LPRECT)&rc);
  442. lpEL->nColPos[2] = rc.left - nStart;
  443. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  444. ULONG cLinks = LoadLinkLB(hListBox, lpOleUILinkCntr);
  445. if ((int)cLinks < 0)
  446. return FALSE;
  447. BOOL fDlgItem = (BOOL)cLinks;
  448. lpEL->fItemsExist = (BOOL)cLinks;
  449. InitControls(hDlg, lpEL);
  450. // Copy other information from lpOEL that we might modify.
  451. // If we got a font, send it to the necessary controls.
  452. if (NULL != hFont)
  453. {
  454. // Do this for as many controls as you need it for.
  455. // SendDlgItemMessage(hDlg, ID_<UFILL>, WM_SETFONT, (WPARAM)hFont, 0L);
  456. }
  457. // Show or hide the help button
  458. if (!(lpEL->lpOEL->dwFlags & ELF_SHOWHELP))
  459. StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE);
  460. /*
  461. * PERFORM OTHER INITIALIZATION HERE. ON ANY LoadString
  462. * FAILURE POST OLEUI_MSG_ENDDIALOG WITH OLEUI_ERR_LOADSTRING.
  463. */
  464. // If requested disable UpdateNow button
  465. if ((lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW))
  466. StandardShowDlgItem(hDlg, IDC_EL_UPDATENOW, SW_HIDE);
  467. // If requested disable OpenSource button
  468. if ((lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE))
  469. StandardShowDlgItem(hDlg, IDC_EL_OPENSOURCE, SW_HIDE);
  470. // If requested disable UpdateNow button
  471. if ((lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE))
  472. StandardShowDlgItem(hDlg, IDC_EL_CHANGESOURCE, SW_HIDE);
  473. // If requested disable CancelLink button
  474. if ((lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK))
  475. StandardShowDlgItem(hDlg, IDC_EL_CANCELLINK, SW_HIDE);
  476. // Change the caption
  477. if (NULL!=lpOEL->lpszCaption)
  478. SetWindowText(hDlg, lpOEL->lpszCaption);
  479. // Load 'Close' string used to rename Cancel button
  480. int n = LoadString(_g_hOleStdResInst, IDS_CLOSE, lpEL->szClose, sizeof(lpEL->szClose)/sizeof(TCHAR));
  481. if (!n)
  482. {
  483. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
  484. return FALSE;
  485. }
  486. if (cLinks > 0)
  487. SetFocus(hListBox);
  488. else
  489. SetFocus(GetDlgItem(hDlg, IDCANCEL));
  490. lpEL->nChgSrcHelpID = RegisterWindowMessage(HELPMSGSTRING);
  491. // Call the hook with lCustData in lParam
  492. UStandardHook(lpEL, hDlg, WM_INITDIALOG, wParam, lpOEL->lCustData);
  493. return FALSE;
  494. }
  495. /*
  496. * Container_ChangeSource
  497. *
  498. * Purpose:
  499. * Tunnel to File Open type dlg and allow user to select new file
  500. * for file based monikers, OR to change the whole moniker to what
  501. * the user types into the editable field.
  502. *
  503. * Parameters:
  504. * hDlg HWND of the dialog
  505. * LPEDITLINKS Pointer to EditLinks structure (contains all nec.
  506. * info)
  507. *
  508. * Return Value:
  509. * BOOL for now, because we are not using any ole functions
  510. * to return an HRESULT.
  511. * HRESULT HRESULT value indicating success or failure of
  512. * changing the moniker value
  513. */
  514. BOOL Container_ChangeSource(HWND hDlg, LPEDITLINKS lpEL)
  515. {
  516. HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
  517. int FAR* rgIndex;
  518. int cSelItems = GetSelectedItems(hListBox, &rgIndex);
  519. if (cSelItems < 0)
  520. return FALSE;
  521. if (!cSelItems)
  522. return TRUE;
  523. OLEUICHANGESOURCE cs; memset(&cs, 0, sizeof(cs));
  524. cs.cbStruct = sizeof(cs);
  525. cs.hWndOwner = hDlg;
  526. if (lpEL->lpOEL->dwFlags & ELF_SHOWHELP)
  527. cs.dwFlags |= CSF_SHOWHELP;
  528. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  529. cs.lpOleUILinkContainer = lpOleUILinkCntr;
  530. for (int i = cSelItems-1; i >= 0; i--)
  531. {
  532. // allow caller to customize the change source dialog
  533. LPLINKINFO lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0);
  534. cs.lpszDisplayName = lpLI->lpszDisplayName;
  535. cs.dwLink = lpLI->dwLink;
  536. cs.nFileLength = lpLI->clenFileName;
  537. UINT uRet = UStandardHook(lpEL, hDlg, uMsgChangeSource, 0, (LPARAM)&cs);
  538. if (!uRet)
  539. uRet = (OLEUI_OK == OleUIChangeSource(&cs));
  540. if (!uRet)
  541. break; // dialog canceled (cancel for all)
  542. if (!lpEL->fClose)
  543. {
  544. SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose);
  545. lpEL->fClose = TRUE;
  546. }
  547. // update the list box item for the new name
  548. // (note: original lpszDisplayName already freed)
  549. lpLI->fSourceAvailable = (cs.dwFlags & CSF_VALIDSOURCE);
  550. lpLI->lpszDisplayName = cs.lpszDisplayName;
  551. UpdateLinkLBItem(hListBox, rgIndex[i], lpEL, TRUE);
  552. // if differed only in file name, allow user to change all links
  553. if (cs.lpszFrom != NULL && cs.lpszTo != NULL)
  554. ChangeAllLinks(hListBox, lpOleUILinkCntr, cs.lpszFrom, cs.lpszTo);
  555. // must free and NULL out the lpszFrom and lpszTo OUT fields
  556. OleStdFree(cs.lpszFrom);
  557. cs.lpszFrom = NULL;
  558. OleStdFree(cs.lpszTo);
  559. cs.lpszTo = NULL;
  560. }
  561. if (rgIndex != NULL)
  562. OleStdFree(rgIndex);
  563. return TRUE;
  564. }
  565. /*
  566. * Container_AutomaticManual
  567. *
  568. * Purpose:
  569. * To change the selected moniker to manual or automatic update.
  570. *
  571. * Parameters:
  572. * hDlg HWND of the dialog
  573. * FAutoMan Flag indicating AUTO (TRUE/1) or MANUAL(FALSE/0)
  574. * LPEDITLINKS Pointer to EditLinks structure (contains all nec.
  575. * info)
  576. * * this may change - don't know how the linked list
  577. * * of multi-selected items will work.
  578. * Return Value:
  579. * HRESULT HRESULT value indicating success or failure of
  580. * changing the moniker value
  581. */
  582. HRESULT Container_AutomaticManual(HWND hDlg, BOOL fAutoMan, LPEDITLINKS lpEL)
  583. {
  584. HRESULT hErr = NOERROR;
  585. int cSelItems;
  586. int FAR* rgIndex;
  587. int i = 0;
  588. LPLINKINFO lpLI;
  589. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  590. HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
  591. BOOL bUpdate = FALSE;
  592. OleDbgAssert(lpOleUILinkCntr);
  593. /* Change so looks at flag in structure. Only update those that
  594. need to be updated. Make sure to change flag if status changes.
  595. */
  596. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  597. if (cSelItems < 0)
  598. return ResultFromScode(E_FAIL);
  599. if (!cSelItems)
  600. return NOERROR;
  601. HCURSOR hCursorOld = HourGlassOn();
  602. if (!lpEL->fClose)
  603. {
  604. SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose);
  605. lpEL->fClose = TRUE;
  606. }
  607. for (i = 0; i < cSelItems; i++)
  608. {
  609. lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0);
  610. if (fAutoMan)
  611. {
  612. // If switching to AUTOMATIC
  613. if (!lpLI->fIsAuto) // Only change MANUAL links
  614. {
  615. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n"));
  616. hErr=lpOleUILinkCntr->SetLinkUpdateOptions(
  617. lpLI->dwLink,
  618. OLEUPDATE_ALWAYS
  619. );
  620. OLEDBG_END2
  621. lpLI->fIsAuto=TRUE;
  622. lpLI->fIsMarked = TRUE;
  623. bUpdate = TRUE;
  624. }
  625. }
  626. else // If switching to MANUAL
  627. {
  628. if (lpLI->fIsAuto) // Only do AUTOMATIC Links
  629. {
  630. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n"));
  631. hErr=lpOleUILinkCntr->SetLinkUpdateOptions(
  632. lpLI->dwLink,
  633. OLEUPDATE_ONCALL
  634. );
  635. OLEDBG_END2
  636. lpLI->fIsAuto = FALSE;
  637. lpLI->fIsMarked = TRUE;
  638. bUpdate = TRUE;
  639. }
  640. }
  641. if (hErr != NOERROR)
  642. {
  643. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::SetLinkUpdateOptions returned"),hErr);
  644. break;
  645. }
  646. }
  647. if (bUpdate)
  648. RefreshLinkLB(hListBox, lpOleUILinkCntr);
  649. if (rgIndex)
  650. OleStdFree((LPVOID)rgIndex);
  651. HourGlassOff(hCursorOld);
  652. return hErr;
  653. }
  654. HRESULT CancelLink(HWND hDlg, LPEDITLINKS lpEL)
  655. {
  656. HRESULT hErr;
  657. LPMONIKER lpmk;
  658. int cSelItems;
  659. int FAR* rgIndex;
  660. int i = 0;
  661. LPLINKINFO lpLI;
  662. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  663. HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
  664. BOOL bUpdate = FALSE;
  665. OleDbgAssert(lpOleUILinkCntr);
  666. lpmk = NULL;
  667. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  668. if (cSelItems < 0)
  669. return ResultFromScode(E_FAIL);
  670. if (!cSelItems)
  671. return NOERROR;
  672. HCURSOR hCursorOld = HourGlassOn();
  673. for (i = 0; i < cSelItems; i++)
  674. {
  675. lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0);
  676. UINT uRet = PopupMessage(hDlg, IDS_LINKS,
  677. IDS_CONFIRMBREAKLINK, MB_YESNO|MB_ICONQUESTION);
  678. if (uRet == IDNO)
  679. break;
  680. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::CancelLink called\r\n"));
  681. hErr = lpOleUILinkCntr->CancelLink(lpLI->dwLink);
  682. OLEDBG_END2
  683. if (!lpEL->fClose)
  684. {
  685. SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose);
  686. lpEL->fClose = TRUE;
  687. }
  688. if (hErr != NOERROR)
  689. {
  690. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::CancelLink returned"),hErr);
  691. lpLI->fIsMarked = TRUE;
  692. bUpdate = TRUE;
  693. }
  694. else
  695. {
  696. // Delete links that we make null from listbox
  697. SendMessage(hListBox, LB_DELETESTRING, (WPARAM) rgIndex[i], 0L);
  698. int i2;
  699. for (i2 = i + 1; i2 < cSelItems; i2++)
  700. {
  701. if (rgIndex[i2] > rgIndex[i])
  702. rgIndex[i2]--;
  703. }
  704. }
  705. }
  706. if (bUpdate)
  707. RefreshLinkLB(hListBox, lpOleUILinkCntr);
  708. if (rgIndex)
  709. OleStdFree((LPVOID)rgIndex);
  710. HourGlassOff(hCursorOld);
  711. return hErr;
  712. }
  713. /*
  714. * Container_UpdateNow
  715. *
  716. * Purpose:
  717. * Immediately force an update for all (manual) links
  718. *
  719. * Parameters:
  720. * hDlg HWND of the dialog
  721. * LPEDITLINKS Pointer to EditLinks structure (contains all nec. info)
  722. * * this may change - don't know how the linked list
  723. * * of multi-selected items will work.
  724. * Return Value:
  725. * HRESULT HRESULT value indicating success or failure of
  726. * changing the moniker value
  727. */
  728. HRESULT Container_UpdateNow(HWND hDlg, LPEDITLINKS lpEL)
  729. {
  730. HRESULT hErr;
  731. LPLINKINFO lpLI;
  732. int cSelItems;
  733. int FAR* rgIndex;
  734. int i = 0;
  735. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  736. HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
  737. BOOL bUpdate = FALSE;
  738. OleDbgAssert(lpOleUILinkCntr);
  739. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  740. if (cSelItems < 0)
  741. return ResultFromScode(E_FAIL);
  742. if (!cSelItems)
  743. return NOERROR;
  744. HCURSOR hCursorOld = HourGlassOn();
  745. if (!lpEL->fClose)
  746. {
  747. SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose);
  748. lpEL->fClose = TRUE;
  749. }
  750. for (i = 0; i < cSelItems; i++)
  751. {
  752. lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[i], 0);
  753. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::UpdateLink called\r\n"));
  754. hErr = lpOleUILinkCntr->UpdateLink(
  755. lpLI->dwLink,
  756. TRUE,
  757. FALSE
  758. );
  759. OLEDBG_END2
  760. bUpdate = TRUE;
  761. lpLI->fIsMarked = TRUE;
  762. if (hErr != NOERROR)
  763. {
  764. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::UpdateLink returned"),hErr);
  765. break;
  766. }
  767. }
  768. if (bUpdate)
  769. RefreshLinkLB(hListBox, lpOleUILinkCntr);
  770. if (rgIndex)
  771. OleStdFree((LPVOID)rgIndex);
  772. HourGlassOff(hCursorOld);
  773. return hErr;
  774. }
  775. /*
  776. * Container_OpenSource
  777. *
  778. * Purpose:
  779. * Immediately force an update for all (manual) links
  780. *
  781. * Parameters:
  782. * hDlg HWND of the dialog
  783. * LPEDITLINKS Pointer to EditLinks structure (contains all nec.
  784. * info)
  785. *
  786. * Return Value:
  787. * HRESULT HRESULT value indicating success or failure of
  788. * changing the moniker value
  789. */
  790. HRESULT Container_OpenSource(HWND hDlg, LPEDITLINKS lpEL)
  791. {
  792. HRESULT hErr;
  793. int cSelItems;
  794. int FAR* rgIndex;
  795. LPLINKINFO lpLI;
  796. RECT rcPosRect;
  797. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  798. HWND hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
  799. OleDbgAssert(lpOleUILinkCntr);
  800. rcPosRect.top = 0;
  801. rcPosRect.left = 0;
  802. rcPosRect.right = 0;
  803. rcPosRect.bottom = 0;
  804. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  805. if (cSelItems < 0)
  806. return ResultFromScode(E_FAIL);
  807. if (cSelItems != 1) // can't open source for multiple items
  808. return NOERROR;
  809. HCURSOR hCursorOld = HourGlassOn();
  810. if (!lpEL->fClose)
  811. {
  812. SetDlgItemText(hDlg, IDCANCEL, lpEL->szClose);
  813. lpEL->fClose = TRUE;
  814. }
  815. lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, rgIndex[0], 0);
  816. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::OpenLinkSource called\r\n"));
  817. hErr = lpOleUILinkCntr->OpenLinkSource(
  818. lpLI->dwLink
  819. );
  820. OLEDBG_END2
  821. UpdateLinkLBItem(hListBox, rgIndex[0], lpEL, TRUE);
  822. if (hErr != NOERROR) {
  823. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::OpenLinkSource returned"),hErr);
  824. }
  825. if (rgIndex)
  826. OleStdFree((LPVOID)rgIndex);
  827. HourGlassOff(hCursorOld);
  828. return hErr;
  829. }
  830. /* AddLinkLBItem
  831. ** -------------
  832. **
  833. ** Add the item pointed to by lpLI to the Link ListBox and return
  834. ** the index of it in the ListBox
  835. */
  836. int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI, BOOL fGetSelected)
  837. {
  838. HRESULT hErr;
  839. DWORD dwUpdateOpt;
  840. int nIndex;
  841. OleDbgAssert(lpOleUILinkCntr && hListBox && lpLI);
  842. lpLI->fDontFree = FALSE;
  843. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkSource called\r\n"));
  844. hErr = lpOleUILinkCntr->GetLinkSource(
  845. lpLI->dwLink,
  846. (LPTSTR FAR*)&lpLI->lpszDisplayName,
  847. (ULONG FAR*)&lpLI->clenFileName,
  848. (LPTSTR FAR*)&lpLI->lpszFullLinkType,
  849. (LPTSTR FAR*)&lpLI->lpszShortLinkType,
  850. (BOOL FAR*)&lpLI->fSourceAvailable,
  851. fGetSelected ? (BOOL FAR*)&lpLI->fIsSelected : NULL
  852. );
  853. OLEDBG_END2
  854. if (hErr != NOERROR)
  855. {
  856. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkSource returned"),hErr);
  857. PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKSOURCE,
  858. MB_ICONEXCLAMATION | MB_OK);
  859. goto cleanup;
  860. }
  861. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkUpdateOptions called\r\n"));
  862. hErr=lpOleUILinkCntr->GetLinkUpdateOptions(
  863. lpLI->dwLink,
  864. (LPDWORD)&dwUpdateOpt
  865. );
  866. OLEDBG_END2
  867. if (hErr != NOERROR)
  868. {
  869. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkUpdateOptions returned"),hErr);
  870. PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKUPDATEOPTIONS,
  871. MB_ICONEXCLAMATION | MB_OK);
  872. goto cleanup;
  873. }
  874. if (lpLI->fSourceAvailable)
  875. {
  876. if (dwUpdateOpt == OLEUPDATE_ALWAYS)
  877. {
  878. lpLI->fIsAuto = TRUE;
  879. LoadString(_g_hOleStdResInst, IDS_LINK_AUTO, lpLI->lpszAMX,
  880. (int)OleStdGetSize((LPVOID)lpLI->lpszAMX) / sizeof (TCHAR));
  881. }
  882. else
  883. {
  884. lpLI->fIsAuto = FALSE;
  885. LoadString(_g_hOleStdResInst, IDS_LINK_MANUAL, lpLI->lpszAMX,
  886. (int)OleStdGetSize((LPVOID)lpLI->lpszAMX) / sizeof (TCHAR));
  887. }
  888. }
  889. else
  890. LoadString(_g_hOleStdResInst, IDS_LINK_UNKNOWN, lpLI->lpszAMX,
  891. (int)OleStdGetSize((LPVOID)lpLI->lpszAMX) / sizeof (TCHAR));
  892. BreakString(lpLI);
  893. nIndex = (int)SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0,
  894. (LPARAM)lpLI);
  895. if (nIndex == LB_ERR)
  896. {
  897. PopupMessage(hListBox, IDS_LINKS, IDS_ERR_ADDSTRING,
  898. MB_ICONEXCLAMATION | MB_OK);
  899. goto cleanup;
  900. }
  901. return nIndex;
  902. cleanup:
  903. if (lpLI->lpszDisplayName)
  904. OleStdFree((LPVOID)lpLI->lpszDisplayName);
  905. if (lpLI->lpszShortLinkType)
  906. OleStdFree((LPVOID)lpLI->lpszShortLinkType);
  907. if (lpLI->lpszFullLinkType)
  908. OleStdFree((LPVOID)lpLI->lpszFullLinkType);
  909. return -1;
  910. }
  911. /* BreakString
  912. * -----------
  913. *
  914. * Purpose:
  915. * Break the lpszDisplayName into various parts
  916. *
  917. * Parameters:
  918. * lpLI pointer to LINKINFO structure
  919. *
  920. * Returns:
  921. *
  922. */
  923. VOID BreakString(LPLINKINFO lpLI)
  924. {
  925. LPTSTR lpsz;
  926. if (!lpLI->clenFileName ||
  927. (lstrlen(lpLI->lpszDisplayName)==(int)lpLI->clenFileName))
  928. {
  929. lpLI->lpszItemName = NULL;
  930. }
  931. else
  932. {
  933. lpLI->lpszItemName = lpLI->lpszDisplayName + lpLI->clenFileName;
  934. }
  935. // search from last character of filename
  936. lpsz = lpLI->lpszDisplayName + lstrlen(lpLI->lpszDisplayName);
  937. while (lpsz > lpLI->lpszDisplayName)
  938. {
  939. lpsz = CharPrev(lpLI->lpszDisplayName, lpsz);
  940. if ((*lpsz == '\\') || (*lpsz == '/') || (*lpsz == ':'))
  941. break;
  942. }
  943. if (lpsz == lpLI->lpszDisplayName)
  944. lpLI->lpszShortFileName = lpsz;
  945. else
  946. lpLI->lpszShortFileName = CharNext(lpsz);
  947. }
  948. /* GetSelectedItems
  949. * ----------------
  950. *
  951. * Purpose:
  952. * Retrieve the indices of the selected items in the listbox
  953. * Note that *lprgIndex needed to be free after using the function
  954. *
  955. * Parameters:
  956. * hListBox window handle of listbox
  957. * lprgIndex pointer to an integer array to receive the indices
  958. * must be freed afterwards
  959. *
  960. * Returns:
  961. * number of indices retrieved, -1 if error
  962. */
  963. int GetSelectedItems(HWND hListBox, int FAR* FAR* lprgIndex)
  964. {
  965. DWORD cSelItems;
  966. DWORD cCheckItems;
  967. *lprgIndex = NULL;
  968. cSelItems = (DWORD)SendMessage(hListBox, LB_GETSELCOUNT, 0, 0L);
  969. if ((int)cSelItems < 0) // error
  970. return (int)cSelItems;
  971. if (!cSelItems)
  972. return 0;
  973. *lprgIndex = (int FAR*)OleStdMalloc((int)cSelItems * sizeof(int));
  974. cCheckItems = (DWORD)SendMessage(hListBox, LB_GETSELITEMS,
  975. (WPARAM) cSelItems, (LPARAM) (int FAR *) *lprgIndex);
  976. if (cCheckItems == cSelItems)
  977. return (int)cSelItems;
  978. else
  979. {
  980. if (*lprgIndex)
  981. OleStdFree((LPVOID)*lprgIndex);
  982. *lprgIndex = NULL;
  983. return 0;
  984. }
  985. }
  986. /* InitControls
  987. * ------------
  988. *
  989. * Purpose:
  990. * Initialize the state of the Auto/Manual button, Link source/type
  991. * static field, etc in the dialogs according to the selection in the
  992. * listbox
  993. *
  994. * Parameters:
  995. * hDlg handle to the dialog window
  996. */
  997. VOID InitControls(HWND hDlg, LPEDITLINKS lpEL)
  998. {
  999. int cSelItems;
  1000. HWND hListBox;
  1001. int i;
  1002. int FAR* rgIndex;
  1003. LPLINKINFO lpLI;
  1004. LPTSTR lpszType = NULL;
  1005. LPTSTR lpszSource = NULL;
  1006. int cAuto = 0;
  1007. int cManual = 0;
  1008. BOOL bSameType = TRUE;
  1009. BOOL bSameSource = TRUE;
  1010. TCHAR tsz[MAX_PATH];
  1011. LPTSTR lpsz;
  1012. hListBox = GetDlgItem(hDlg, IDC_EL_LINKSLISTBOX);
  1013. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  1014. if (cSelItems < 0)
  1015. return;
  1016. if ((cSelItems > 0) && (rgIndex == NULL))
  1017. return;
  1018. StandardEnableDlgItem(hDlg, IDC_EL_AUTOMATIC, (BOOL)cSelItems);
  1019. StandardEnableDlgItem(hDlg, IDC_EL_MANUAL, (BOOL)cSelItems);
  1020. if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK))
  1021. StandardEnableDlgItem(hDlg, IDC_EL_CANCELLINK, (BOOL)cSelItems);
  1022. if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE))
  1023. StandardEnableDlgItem(hDlg, IDC_EL_OPENSOURCE, cSelItems == 1);
  1024. if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE))
  1025. StandardEnableDlgItem(hDlg, IDC_EL_CHANGESOURCE, cSelItems == 1);
  1026. if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW))
  1027. StandardEnableDlgItem(hDlg, IDC_EL_UPDATENOW, (BOOL)cSelItems);
  1028. for (i = 0; i < cSelItems; i++)
  1029. {
  1030. lpLI = (LPLINKINFO)SendDlgItemMessage(hDlg, IDC_EL_LINKSLISTBOX,
  1031. LB_GETITEMDATA, rgIndex[i], 0);
  1032. if (lpszSource && lpLI->lpszDisplayName)
  1033. {
  1034. if (bSameSource && lstrcmp(lpszSource, lpLI->lpszDisplayName))
  1035. bSameSource = FALSE;
  1036. }
  1037. else
  1038. lpszSource = lpLI->lpszDisplayName;
  1039. if (lpszType && lpLI->lpszFullLinkType)
  1040. {
  1041. if (bSameType && lstrcmp(lpszType, lpLI->lpszFullLinkType))
  1042. bSameType = FALSE;
  1043. }
  1044. else
  1045. lpszType = lpLI->lpszFullLinkType;
  1046. if (lpLI->fIsAuto)
  1047. cAuto++;
  1048. else
  1049. cManual++;
  1050. }
  1051. CheckDlgButton(hDlg, IDC_EL_AUTOMATIC, cAuto && !cManual);
  1052. CheckDlgButton(hDlg, IDC_EL_MANUAL, !cAuto && cManual);
  1053. /* fill full source in static text box
  1054. ** below list
  1055. */
  1056. if (!bSameSource || !lpszSource)
  1057. lpszSource = szNULL;
  1058. lstrcpy(tsz, lpszSource);
  1059. lpsz = ChopText(GetDlgItem(hDlg, IDC_EL_LINKSOURCE), 0, tsz, 0);
  1060. SetDlgItemText(hDlg, IDC_EL_LINKSOURCE, lpsz);
  1061. /* fill full link type name in static
  1062. ** "type" text box
  1063. */
  1064. if (!bSameType || !lpszType)
  1065. lpszType = szNULL;
  1066. SetDlgItemText(hDlg, IDC_EL_LINKTYPE, lpszType);
  1067. if (rgIndex)
  1068. OleStdFree((LPVOID)rgIndex);
  1069. }
  1070. /* UpdateLinkLBItem
  1071. * -----------------
  1072. *
  1073. * Purpose:
  1074. * Update the linkinfo struct in the listbox to reflect the changes
  1075. * made by the last operation. It is done simply by removing the item
  1076. * from the listbox and add it back.
  1077. *
  1078. * Parameters:
  1079. * hListBox handle of listbox
  1080. * nIndex index of listbox item
  1081. * lpEL pointer to editlinks structure
  1082. * bSelect select the item or not after update
  1083. */
  1084. VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect)
  1085. {
  1086. LPLINKINFO lpLI;
  1087. LPOLEUILINKCONTAINER lpOleUILinkCntr;
  1088. if (!hListBox || (nIndex < 0) || !lpEL)
  1089. return;
  1090. lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  1091. lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, nIndex, 0);
  1092. if (lpLI == NULL)
  1093. return;
  1094. /* Don't free the data associated with this listbox item
  1095. ** because we are going to reuse the allocated space for
  1096. ** the modified link. WM_DELETEITEM processing in the
  1097. ** dialog checks this flag before deleting data
  1098. ** associcated with list item.
  1099. */
  1100. lpLI->fDontFree = TRUE;
  1101. SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L);
  1102. nIndex = AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE);
  1103. if (bSelect)
  1104. {
  1105. SendMessage(hListBox, LB_SETSEL, TRUE, MAKELPARAM(nIndex, 0));
  1106. SendMessage(hListBox, LB_SETCARETINDEX, nIndex, MAKELPARAM(TRUE, 0));
  1107. }
  1108. }
  1109. /* ChangeAllLinks
  1110. * --------------
  1111. *
  1112. * Purpose:
  1113. * Enumerate all the links in the listbox and change those starting
  1114. * with lpszFrom to lpszTo.
  1115. *
  1116. * Parameters:
  1117. * hListBox window handle of
  1118. * lpOleUILinkCntr pointer to OleUI Link Container
  1119. * lpszFrom prefix for matching
  1120. * lpszTo prefix to substitution
  1121. *
  1122. * Returns:
  1123. */
  1124. VOID ChangeAllLinks(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo)
  1125. {
  1126. int cItems;
  1127. int nIndex;
  1128. int cFrom;
  1129. LPLINKINFO lpLI;
  1130. TCHAR szTmp[MAX_PATH];
  1131. BOOL bFound;
  1132. cFrom = lstrlen(lpszFrom);
  1133. cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L);
  1134. OleDbgAssert(cItems >= 0);
  1135. bFound = FALSE;
  1136. #ifdef _DEBUG
  1137. OleDbgPrint(3, TEXT("From : "), lpszFrom, 0);
  1138. OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0);
  1139. OleDbgPrint(3, TEXT("To : "), lpszTo, 0);
  1140. OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0);
  1141. #endif
  1142. for (nIndex = 0; nIndex < cItems; nIndex++)
  1143. {
  1144. lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, nIndex, 0);
  1145. // unmark the item
  1146. lpLI->fIsMarked = FALSE;
  1147. /* if the corresponding position for the end of lpszFrom in the
  1148. ** display name is not a separator. We stop comparing this
  1149. ** link.
  1150. */
  1151. if (!*(lpLI->lpszDisplayName + cFrom) ||
  1152. (*(lpLI->lpszDisplayName + cFrom) == '\\') ||
  1153. (*(lpLI->lpszDisplayName + cFrom) == '!'))
  1154. {
  1155. lstrcpyn(szTmp, lpLI->lpszDisplayName, cFrom + 1);
  1156. if (!lstrcmp(szTmp, lpszFrom))
  1157. {
  1158. HRESULT hErr;
  1159. int nFileLength;
  1160. ULONG ulDummy;
  1161. if (!bFound)
  1162. {
  1163. TCHAR szTitle[256];
  1164. TCHAR szMsg[256];
  1165. TCHAR szBuf[256];
  1166. int uRet;
  1167. LoadString(_g_hOleStdResInst, IDS_CHANGESOURCE, szTitle,
  1168. sizeof(szTitle)/sizeof(TCHAR));
  1169. LoadString(_g_hOleStdResInst, IDS_CHANGEADDITIONALLINKS,
  1170. szMsg, sizeof(szMsg)/sizeof(TCHAR));
  1171. wsprintf(szBuf, szMsg, lpszFrom);
  1172. uRet = MessageBox(hListBox, szBuf, szTitle,
  1173. MB_ICONQUESTION | MB_YESNO);
  1174. if (uRet == IDYES)
  1175. bFound = TRUE;
  1176. else
  1177. return;
  1178. }
  1179. lstrcpy(szTmp, lpszTo);
  1180. lstrcat(szTmp, lpLI->lpszDisplayName + cFrom);
  1181. nFileLength = lstrlen(szTmp) -
  1182. (lpLI->lpszItemName ? lstrlen(lpLI->lpszItemName) : 0);
  1183. hErr = lpOleUILinkCntr->SetLinkSource(
  1184. lpLI->dwLink,
  1185. szTmp,
  1186. (ULONG)nFileLength,
  1187. (ULONG FAR*)&ulDummy,
  1188. TRUE
  1189. );
  1190. if (hErr != NOERROR)
  1191. {
  1192. lpOleUILinkCntr->SetLinkSource(
  1193. lpLI->dwLink,
  1194. szTmp,
  1195. (ULONG)nFileLength,
  1196. (ULONG FAR*)&ulDummy,
  1197. FALSE);
  1198. }
  1199. lpLI->fIsMarked = TRUE;
  1200. }
  1201. }
  1202. }
  1203. /* have to do the refreshing after processing all links, otherwise
  1204. ** the item positions will change during the process as the
  1205. ** listbox stores items in order
  1206. */
  1207. if (bFound)
  1208. RefreshLinkLB(hListBox, lpOleUILinkCntr);
  1209. }
  1210. /* LoadLinkLB
  1211. * ----------
  1212. *
  1213. * Purpose:
  1214. * Enumerate all links from the Link Container and build up the Link
  1215. * ListBox
  1216. *
  1217. * Parameters:
  1218. * hListBox window handle of
  1219. * lpOleUILinkCntr pointer to OleUI Link Container
  1220. * lpszFrom prefix for matching
  1221. * lpszTo prefix to substitution
  1222. *
  1223. * Returns:
  1224. * number of link items loaded, -1 if error
  1225. */
  1226. int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr)
  1227. {
  1228. DWORD dwLink = 0;
  1229. LPLINKINFO lpLI;
  1230. int nIndex;
  1231. int cLinks;
  1232. cLinks = 0;
  1233. while ((dwLink = lpOleUILinkCntr->GetNextLink(dwLink)) != 0)
  1234. {
  1235. lpLI = (LPLINKINFO)OleStdMalloc(sizeof(LINKINFO));
  1236. if (NULL == lpLI)
  1237. return -1;
  1238. lpLI->fIsMarked = FALSE;
  1239. lpLI->fIsSelected = FALSE;
  1240. lpLI->fDontFree = FALSE;
  1241. lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(TCHAR));
  1242. lpLI->dwLink = dwLink;
  1243. cLinks++;
  1244. if ((nIndex = AddLinkLBItem(hListBox,lpOleUILinkCntr,lpLI,TRUE)) < 0)
  1245. // can't load list box
  1246. return -1;
  1247. if (lpLI->fIsSelected)
  1248. SendMessage(hListBox, LB_SETSEL, TRUE, MAKELPARAM(nIndex, 0));
  1249. }
  1250. if (SendMessage(hListBox,LB_GETSELITEMS,(WPARAM)1,(LPARAM)(int FAR*)&nIndex))
  1251. SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, MAKELPARAM(TRUE, 0));
  1252. return cLinks;
  1253. }
  1254. /* RefreshLinkLB
  1255. * -------------
  1256. *
  1257. * Purpose:
  1258. * Enumerate all items in the links listbox and update those with
  1259. * fIsMarked set.
  1260. * Note that this is a time consuming routine as it keeps iterating
  1261. * all items in the listbox until all of them are unmarked.
  1262. *
  1263. * Parameters:
  1264. * hListBox window handle of listbox
  1265. * lpOleUILinkCntr pointer to OleUI Link Container
  1266. *
  1267. * Returns:
  1268. *
  1269. */
  1270. VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr)
  1271. {
  1272. int cItems;
  1273. int nIndex;
  1274. LPLINKINFO lpLI;
  1275. BOOL bStop;
  1276. OleDbgAssert(hListBox);
  1277. cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L);
  1278. OleDbgAssert(cItems >= 0);
  1279. do
  1280. {
  1281. bStop = TRUE;
  1282. for (nIndex = 0; nIndex < cItems; nIndex++)
  1283. {
  1284. lpLI = (LPLINKINFO)SendMessage(hListBox, LB_GETITEMDATA, nIndex, 0);
  1285. if (lpLI->fIsMarked)
  1286. {
  1287. lpLI->fIsMarked = FALSE;
  1288. lpLI->fDontFree = TRUE;
  1289. SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L);
  1290. nIndex=AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE);
  1291. if (lpLI->fIsSelected)
  1292. {
  1293. SendMessage(hListBox, LB_SETSEL, (WPARAM)TRUE,
  1294. MAKELPARAM(nIndex, 0));
  1295. SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex,
  1296. MAKELPARAM(TRUE, 0));
  1297. }
  1298. bStop = FALSE;
  1299. break;
  1300. }
  1301. }
  1302. } while (!bStop);
  1303. }