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.

2146 lines
65 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. #define STRICT 1
  10. #include "ole2ui.h"
  11. #include "common.h"
  12. #include "edlinks.h"
  13. #include "utility.h"
  14. #include <commdlg.h>
  15. #include <dlgs.h>
  16. #include <stdlib.h>
  17. OLEDBGDATA
  18. /*
  19. * OleUIEditLinks
  20. *
  21. * Purpose:
  22. * Invokes the standard OLE Edit Links dialog box allowing the user
  23. * to manipulate ole links (delete, update, change source, etc).
  24. *
  25. * Parameters:
  26. * lpEL LPOLEUIEditLinks pointing to the in-out structure
  27. * for this dialog.
  28. *
  29. * Return Value:
  30. * UINT One of the following codes, indicating success or error:
  31. * OLEUI_SUCCESS Success
  32. * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong
  33. */
  34. STDAPI_(UINT) OleUIEditLinks(LPOLEUIEDITLINKS lpEL)
  35. {
  36. UINT uRet;
  37. HGLOBAL hMemDlg=NULL;
  38. uRet=UStandardValidation((LPOLEUISTANDARD)lpEL, sizeof(OLEUIEDITLINKS)
  39. , &hMemDlg);
  40. if (OLEUI_SUCCESS!=uRet)
  41. return uRet;
  42. /*
  43. * PERFORM ANY STRUCTURE-SPECIFIC VALIDATION HERE!
  44. * ON FAILURE:
  45. * {
  46. * if (NULL!=hMemDlg)
  47. * FreeResource(hMemDlg)
  48. *
  49. * return OLEUI_<ABBREV>ERR_<ERROR>
  50. * }
  51. */
  52. //Now that we've validated everything, we can invoke the dialog.
  53. uRet=UStandardInvocation(EditLinksDialogProc, (LPOLEUISTANDARD)lpEL,
  54. hMemDlg, MAKEINTRESOURCE(IDD_EDITLINKS));
  55. /*
  56. * IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE.
  57. */
  58. return uRet;
  59. }
  60. /*
  61. * EditLinksDialogProc
  62. *
  63. * Purpose:
  64. * Implements the OLE Edit Links dialog as invoked through the
  65. * OleUIEditLinks function.
  66. *
  67. * Parameters:
  68. * Standard
  69. *
  70. * Return Value:
  71. * Standard
  72. */
  73. BOOL CALLBACK EXPORT EditLinksDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  74. {
  75. LPEDITLINKS lpEL = NULL;
  76. BOOL fHook=FALSE;
  77. UINT uRet=0;
  78. HRESULT hErr;
  79. static int nColPos[3];
  80. //Declare Win16/Win32 compatible WM_COMMAND parameters.
  81. COMMANDPARAMS(wID, wCode, hWndMsg);
  82. //This will fail under WM_INITDIALOG, where we allocate it.
  83. lpEL=(LPEDITLINKS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
  84. //If the hook processed the message, we're done.
  85. if (0!=uRet)
  86. return (BOOL)uRet;
  87. // Process help message from secondary dialog
  88. if (iMsg == uMsgHelp) {
  89. PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp, wParam, lParam);
  90. return FALSE;
  91. }
  92. //Process the temination message
  93. if (iMsg==uMsgEndDialog) {
  94. //Free any specific allocations before calling StandardCleanup
  95. StandardCleanup(lpEL, hDlg);
  96. EndDialog(hDlg, wParam);
  97. return TRUE;
  98. }
  99. switch (iMsg) {
  100. static int nHeightLine = -1;
  101. static int nMaxCharWidth = -1;
  102. case WM_INITDIALOG:
  103. {
  104. RECT rc;
  105. int nStart;
  106. /* calculate the column positions relative to the listbox */
  107. GetWindowRect(GetDlgItem(hDlg, ID_EL_LINKSLISTBOX), (LPRECT)&rc);
  108. nStart = rc.left;
  109. GetWindowRect(GetDlgItem(hDlg, ID_EL_COL1), (LPRECT)&rc);
  110. nColPos[0] = rc.left - nStart;
  111. GetWindowRect(GetDlgItem(hDlg, ID_EL_COL2), (LPRECT)&rc);
  112. nColPos[1] = rc.left - nStart;
  113. GetWindowRect(GetDlgItem(hDlg, ID_EL_COL3), (LPRECT)&rc);
  114. nColPos[2] = rc.left - nStart;
  115. return FEditLinksInit(hDlg, wParam, lParam);
  116. }
  117. break;
  118. case WM_MEASUREITEM:
  119. {
  120. LPMEASUREITEMSTRUCT lpMIS;
  121. lpMIS = (LPMEASUREITEMSTRUCT)lParam;
  122. if (nHeightLine == -1) {
  123. HFONT hFont;
  124. HDC hDC;
  125. TEXTMETRIC tm;
  126. /* Attempt to get font dialog. If that fails,
  127. use system font
  128. */
  129. hFont = (HANDLE)(UINT)SendMessage(hDlg, WM_GETFONT, 0, 0L);
  130. if (hFont == NULL)
  131. hFont = GetStockObject(SYSTEM_FONT);
  132. hDC = GetDC(hDlg);
  133. hFont = SelectObject(hDC, hFont);
  134. GetTextMetrics(hDC, &tm);
  135. nHeightLine = tm.tmHeight;
  136. nMaxCharWidth = tm.tmMaxCharWidth;
  137. ReleaseDC(hDlg, hDC);
  138. }
  139. lpMIS->itemHeight = nHeightLine;
  140. }
  141. break;
  142. case WM_DRAWITEM:
  143. {
  144. LPDRAWITEMSTRUCT lpDIS;
  145. COLORREF crText;
  146. LPLINKINFO lpLI;
  147. HBRUSH hbr;
  148. int nOldBkMode;
  149. TCHAR tsz[OLEUI_CCHPATHMAX];
  150. LPTSTR lpsz;
  151. RECT rcClip;
  152. lpDIS = (LPDRAWITEMSTRUCT)lParam;
  153. lpLI = (LPLINKINFO)lpDIS->itemData;
  154. if ((int)lpDIS->itemID < 0)
  155. break;
  156. if ((ODA_DRAWENTIRE | ODA_SELECT) & lpDIS->itemAction) {
  157. if (ODS_SELECTED & lpDIS->itemState) {
  158. /*Get proper txt colors */
  159. crText = SetTextColor(lpDIS->hDC,
  160. GetSysColor(COLOR_HIGHLIGHTTEXT));
  161. hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
  162. lpLI->fIsSelected = TRUE;
  163. }
  164. else {
  165. hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  166. lpLI->fIsSelected = FALSE;
  167. }
  168. FillRect(lpDIS->hDC, &lpDIS->rcItem, hbr);
  169. DeleteObject(hbr);
  170. nOldBkMode = SetBkMode(lpDIS->hDC, TRANSPARENT);
  171. if (lpLI->lpszDisplayName) {
  172. lstrcpy((LPTSTR)tsz, lpLI->lpszDisplayName);
  173. lpsz = ChopText(
  174. lpDIS->hwndItem,
  175. nColPos[1] - nColPos[0]
  176. - (nMaxCharWidth > 0 ? nMaxCharWidth : 5),
  177. tsz
  178. );
  179. rcClip.left = lpDIS->rcItem.left + nColPos[0];
  180. rcClip.top = lpDIS->rcItem.top;
  181. rcClip.right = lpDIS->rcItem.left + nColPos[1]
  182. - (nMaxCharWidth > 0 ? nMaxCharWidth : 5);
  183. rcClip.bottom = lpDIS->rcItem.bottom;
  184. ExtTextOut(
  185. lpDIS->hDC,
  186. rcClip.left,
  187. rcClip.top,
  188. ETO_CLIPPED,
  189. (LPRECT)&rcClip,
  190. lpsz,
  191. lstrlen(lpsz),
  192. NULL
  193. );
  194. }
  195. if (lpLI->lpszShortLinkType) {
  196. rcClip.left = lpDIS->rcItem.left + nColPos[1];
  197. rcClip.top = lpDIS->rcItem.top;
  198. rcClip.right = lpDIS->rcItem.left + nColPos[2]
  199. - (nMaxCharWidth > 0 ? nMaxCharWidth : 5);
  200. rcClip.bottom = lpDIS->rcItem.bottom;
  201. ExtTextOut(
  202. lpDIS->hDC,
  203. rcClip.left,
  204. rcClip.top,
  205. ETO_CLIPPED,
  206. (LPRECT)&rcClip,
  207. lpLI->lpszShortLinkType,
  208. lstrlen(lpLI->lpszShortLinkType),
  209. NULL
  210. );
  211. }
  212. if (lpLI->lpszAMX) {
  213. rcClip.left = lpDIS->rcItem.left + nColPos[2];
  214. rcClip.top = lpDIS->rcItem.top;
  215. rcClip.right = lpDIS->rcItem.right;
  216. rcClip.bottom = lpDIS->rcItem.bottom;
  217. ExtTextOut(
  218. lpDIS->hDC,
  219. rcClip.left,
  220. rcClip.top,
  221. ETO_CLIPPED,
  222. (LPRECT)&rcClip,
  223. lpLI->lpszAMX,
  224. lstrlen(lpLI->lpszAMX),
  225. NULL
  226. );
  227. }
  228. SetBkMode(lpDIS->hDC, nOldBkMode);
  229. // restore orig colors if we changed them
  230. if (ODS_SELECTED & lpDIS->itemState)
  231. SetTextColor(lpDIS->hDC, crText);
  232. }
  233. InitControls(hDlg, lpEL);
  234. if (ODA_FOCUS & lpDIS->itemAction)
  235. DrawFocusRect(lpDIS->hDC, &lpDIS->rcItem);
  236. }
  237. return TRUE;
  238. case WM_DELETEITEM:
  239. {
  240. UINT idCtl;
  241. LPDELETEITEMSTRUCT lpDIS;
  242. LPLINKINFO lpLI;
  243. lpDIS = (LPDELETEITEMSTRUCT)lParam;
  244. idCtl = wParam;
  245. lpLI = (LPLINKINFO)lpDIS->itemData;
  246. if (lpLI->lpszDisplayName)
  247. OleStdFree((LPVOID)lpLI->lpszDisplayName);
  248. if (lpLI->lpszShortLinkType)
  249. OleStdFree((LPVOID)lpLI->lpszShortLinkType);
  250. if (lpLI->lpszFullLinkType)
  251. OleStdFree((LPVOID)lpLI->lpszFullLinkType);
  252. /* The ChangeSource processing reuses allocated space for
  253. ** links that have been modified.
  254. */
  255. // Don't free the LINKINFO for the changed links
  256. if (lpLI->fDontFree)
  257. lpLI->fDontFree = FALSE;
  258. else {
  259. if (lpLI->lpszAMX)
  260. OleStdFree((LPVOID)lpLI->lpszAMX);
  261. OleStdFree((LPVOID)lpLI);
  262. }
  263. return TRUE;
  264. }
  265. case WM_COMPAREITEM:
  266. {
  267. LPCOMPAREITEMSTRUCT lpCIS = (LPCOMPAREITEMSTRUCT)lParam;
  268. LPLINKINFO lpLI1 = (LPLINKINFO)lpCIS->itemData1;
  269. LPLINKINFO lpLI2 = (LPLINKINFO)lpCIS->itemData2;
  270. // Sort list entries by DisplayName
  271. return lstrcmp(lpLI1->lpszDisplayName,lpLI2->lpszDisplayName);
  272. }
  273. case WM_COMMAND:
  274. switch (wID) {
  275. case ID_EL_CHANGESOURCE:
  276. {
  277. BOOL fRet = FALSE;
  278. /* This will bring up the file open dlg with one
  279. edit field containing the whole link name. The file part
  280. will (eventually) be highlighted to indicate where the
  281. file part is. We need to hook on OK here to be able to
  282. send the changed string to the Parse function */
  283. fRet = Container_ChangeSource(hDlg, lpEL);
  284. if (!fRet)
  285. PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
  286. MB_ICONEXCLAMATION | MB_OK);
  287. InitControls(hDlg, lpEL);
  288. }
  289. break;
  290. case ID_EL_AUTOMATIC:
  291. {
  292. /* This is available for single or multi-select. There is
  293. a flag in the structure that is set initially indicating
  294. whether the link is auto or manual so that we need not
  295. query the link each time we want to find out.
  296. This command will make the link automatic if not already.
  297. It will have no effect on links already set to auto.
  298. */
  299. // turn the button ON
  300. CheckDlgButton(hDlg, ID_EL_AUTOMATIC, 1);
  301. CheckDlgButton(hDlg, ID_EL_MANUAL, 0);
  302. hErr = Container_AutomaticManual(hDlg, TRUE, lpEL);
  303. if (hErr != NOERROR)
  304. PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
  305. MB_ICONEXCLAMATION | MB_OK);
  306. InitControls(hDlg, lpEL);
  307. }
  308. break;
  309. case ID_EL_MANUAL:
  310. {
  311. /* Same rules apply here as they do to auto link.
  312. Additional note - just because something is changed does
  313. not mean that it updates at the moment. It simply
  314. reflects what kind of updating it does while it lives in
  315. the document.
  316. */
  317. // turn the button ON
  318. CheckDlgButton(hDlg, ID_EL_MANUAL, 1);
  319. CheckDlgButton(hDlg, ID_EL_AUTOMATIC, 0);
  320. hErr = Container_AutomaticManual(hDlg, FALSE, lpEL);
  321. if (hErr != NOERROR)
  322. PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
  323. MB_ICONEXCLAMATION | MB_OK);
  324. InitControls(hDlg, lpEL);
  325. }
  326. break;
  327. case ID_EL_CANCELLINK:
  328. {
  329. /* This is Break Link now in the dlg. This sets the
  330. moniker to null, thereby effectively breaking the link.
  331. The object still has its data effective at the time of
  332. breaking, but becomes a static object.
  333. *****It will need to be deleted from the listbox
  334. */
  335. CancelLink(hDlg,lpEL);
  336. InitControls(hDlg, lpEL);
  337. }
  338. break;
  339. case ID_EL_UPDATENOW:
  340. {
  341. /* This forces an immediate update of the selected
  342. links. This will start the server etc, so this is a very
  343. expensive operation.
  344. */
  345. hErr = Container_UpdateNow(hDlg, lpEL);
  346. InitControls(hDlg, lpEL);
  347. }
  348. break;
  349. case ID_EL_OPENSOURCE:
  350. {
  351. /* This will only work on single selection. It makes no
  352. sense to open multiple sources at the same time, since
  353. the one opened will try to show itself and become the
  354. primary operating target, so to speak. Button is greyed
  355. if multi select.
  356. Here we do not add the break because we want to exit the
  357. dlg in this case.
  358. */
  359. hErr = Container_OpenSource(hDlg, lpEL);
  360. if (hErr != NOERROR) {
  361. InitControls(hDlg, lpEL);
  362. break; // don't close dialog
  363. }
  364. } // fall through
  365. case ID_EL_CLOSE:
  366. {
  367. /* The user is finished with their editing - they now
  368. return to their container document.
  369. */
  370. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  371. }
  372. break;
  373. case IDCANCEL:
  374. {
  375. /* This changes to CLOSE after the user does even ONE
  376. thing in the dlg. Nothing can really effectively be undone.
  377. */
  378. SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
  379. }
  380. break;
  381. case ID_OLEUIHELP:
  382. {
  383. PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp
  384. , (WPARAM)hDlg, MAKELPARAM(IDD_EDITLINKS, 0));
  385. break;
  386. }
  387. break;
  388. }
  389. break;
  390. default:
  391. {
  392. if (lpEL && iMsg == lpEL->nChgSrcHelpID) {
  393. PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp,
  394. (WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0));
  395. }
  396. }
  397. break;
  398. }
  399. return FALSE;
  400. }
  401. /*
  402. * FEditLinksInit
  403. *
  404. * Purpose:
  405. * WM_INITIDIALOG handler for the Edit Links dialog box.
  406. *
  407. *
  408. * Parameters:
  409. * hDlg HWND of the dialog
  410. * wParam WPARAM of the message
  411. * lParam LPARAM of the message
  412. *
  413. * Return Value:
  414. * BOOL Value to return for WM_INITDIALOG.
  415. */
  416. BOOL FEditLinksInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
  417. {
  418. LPEDITLINKS lpEL;
  419. LPOLEUIEDITLINKS lpOEL;
  420. HFONT hFont;
  421. BOOL fDlgItem = FALSE;
  422. DWORD dwLink = 0;
  423. ULONG cLinks;
  424. LPOLEUILINKCONTAINER lpOleUILinkCntr;
  425. int n;
  426. HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
  427. //1. Copy the structure at lParam into our instance memory.
  428. lpEL = (LPEDITLINKS)LpvStandardInit(hDlg, sizeof(OLEUIEDITLINKS), TRUE,
  429. &hFont);
  430. //PvStandardInit send a termination to us already.
  431. if (NULL==lpEL)
  432. return FALSE;
  433. lpOEL=(LPOLEUIEDITLINKS)lParam;
  434. lpEL->lpOEL=lpOEL;
  435. lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  436. cLinks = LoadLinkLB(hListBox, lpOleUILinkCntr);
  437. if (cLinks < 0)
  438. return FALSE;
  439. fDlgItem = (BOOL)cLinks;
  440. lpEL->fItemsExist = (BOOL)cLinks;
  441. InitControls(hDlg, lpEL);
  442. //Copy other information from lpOEL that we might modify.
  443. //2. If we got a font, send it to the necessary controls.
  444. if (NULL != hFont) {
  445. // Do this for as many controls as you need it for.
  446. // SendDlgItemMessage(hDlg, ID_<UFILL>, WM_SETFONT, (WPARAM)hFont, 0L);
  447. }
  448. //3. Show or hide the help button
  449. if (!(lpEL->lpOEL->dwFlags & ELF_SHOWHELP))
  450. StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
  451. /*
  452. * PERFORM OTHER INITIALIZATION HERE. ON ANY LoadString
  453. * FAILURE POST OLEUI_MSG_ENDDIALOG WITH OLEUI_ERR_LOADSTRING.
  454. */
  455. //4. If requested disable UpdateNow button
  456. if ((lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW))
  457. StandardShowDlgItem(hDlg, ID_EL_UPDATENOW, SW_HIDE);
  458. //5. If requested disable OpenSource button
  459. if ((lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE))
  460. StandardShowDlgItem(hDlg, ID_EL_OPENSOURCE, SW_HIDE);
  461. //6. If requested disable UpdateNow button
  462. if ((lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE))
  463. StandardShowDlgItem(hDlg, ID_EL_CHANGESOURCE, SW_HIDE);
  464. //7. If requested disable CancelLink button
  465. if ((lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK))
  466. StandardShowDlgItem(hDlg, ID_EL_CANCELLINK, SW_HIDE);
  467. //8. Load 'Close' string used to rename Cancel button
  468. n = LoadString(ghInst, IDS_CLOSE, lpEL->szClose, sizeof(lpEL->szClose)/sizeof(TCHAR));
  469. if (!n)
  470. {
  471. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
  472. return FALSE;
  473. }
  474. if (cLinks > 0)
  475. SetFocus(hListBox);
  476. else
  477. SetFocus(GetDlgItem(hDlg, IDCANCEL));
  478. lpEL->nChgSrcHelpID = RegisterWindowMessage(HELPMSGSTRING);
  479. //n. Call the hook with lCustData in lParam
  480. UStandardHook(lpEL, hDlg, WM_INITDIALOG, wParam, lpOEL->lCustData);
  481. return FALSE;
  482. }
  483. /*
  484. * ChangeSourceHook
  485. *
  486. * Purpose:
  487. * Hooks the ChangeSource dialog to attempt to validate link source changes
  488. * specified by the user.
  489. *
  490. * Parameters:
  491. * hDlg HWND of the dialog
  492. * uMsg UINT Message
  493. * wParam WPARAM of the message
  494. * lParam LPARAM of the message
  495. *
  496. * Return Value:
  497. * UNIT Zero = Do default processing;
  498. * Non Zero = Don't do default processing.
  499. */
  500. UINT CALLBACK EXPORT ChangeSourceHook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  501. {
  502. LPCHANGESOURCEHOOKDATA lpCshData = NULL;
  503. LPLINKINFO lpLI = NULL;
  504. LPEDITLINKS lpEL = NULL;
  505. LPOLEUILINKCONTAINER lpOleUILinkCntr;
  506. HRESULT hErr;
  507. UINT uRet;
  508. ULONG ulChEaten;
  509. HGLOBAL gh;
  510. //This will fail under WM_INITDIALOG, where we allocate it.
  511. if (NULL!=(gh = GetProp(hDlg, STRUCTUREPROP)))
  512. {
  513. // gh was locked previously, lock and unlock to get lpv
  514. lpCshData=(LPCHANGESOURCEHOOKDATA)GlobalLock(gh);
  515. GlobalUnlock(gh);
  516. if (lpCshData)
  517. {
  518. lpLI = lpCshData->lpOCshData->lpLI;
  519. lpEL = lpCshData->lpOCshData->lpEL;
  520. }
  521. }
  522. //Process the temination message
  523. if (uMsg==uMsgEndDialog)
  524. {
  525. if (NULL!=(gh = RemoveProp(hDlg, STRUCTUREPROP)))
  526. {
  527. GlobalUnlock(gh);
  528. GlobalFree(gh);
  529. }
  530. return TRUE;
  531. }
  532. // User pressed the OK button
  533. if (uMsg == uMsgFileOKString) {
  534. lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  535. /* NOTE: trigger the focus lost of the edit control. This is
  536. ** not necessary if the user click OK with the mouse but is
  537. ** needed when the user just press <Enter>. If the mouse was
  538. ** used, no extra is done as the MODIFY flag of the edit control
  539. ** has been cleared.
  540. */
  541. SendMessage(hDlg, WM_COMMAND, edt1,
  542. MAKELPARAM(GetDlgItem(hDlg, edt1), EN_KILLFOCUS));
  543. if (lpCshData->bItemNameStored) {
  544. lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit) -
  545. lstrlen((LPTSTR)lpCshData->szItemName);
  546. }
  547. else {
  548. lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit);
  549. }
  550. // Try to validate link source change
  551. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkSource called\r\n"));
  552. hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource(
  553. lpOleUILinkCntr,
  554. lpLI->dwLink,
  555. (LPTSTR)lpCshData->szEdit,
  556. (ULONG)lpCshData->nFileLength,
  557. &ulChEaten,
  558. TRUE
  559. );
  560. OLEDBG_END2
  561. // Link source change not validated
  562. if (hErr != NOERROR) {
  563. uRet =PopupMessage(hDlg, IDS_CHANGESOURCE, IDS_INVALIDSOURCE,
  564. MB_ICONQUESTION | MB_YESNO);
  565. if (uRet == IDYES) {
  566. /* User wants to correct invalid link. Set the edit
  567. ** control selection to the invalid part of the contents.
  568. */
  569. SetFocus(GetDlgItem(hDlg, edt1));
  570. SendDlgItemMessage(hDlg, edt1, EM_SETSEL, 0,
  571. MAKELPARAM(ulChEaten, -1));
  572. return 1; // Don't close ChangeSource dialog
  573. }
  574. else {
  575. /* User does not want to correct invalid link. So set
  576. ** the link source but don't validate the link.
  577. */
  578. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkSource called\r\n"));
  579. hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource(
  580. lpOleUILinkCntr,
  581. lpLI->dwLink,
  582. (LPTSTR)lpCshData->szEdit,
  583. (ULONG)lpCshData->nFileLength,
  584. &ulChEaten,
  585. FALSE
  586. );
  587. OLEDBG_END2
  588. lpCshData->fValidLink = FALSE;
  589. }
  590. }
  591. else { // Link source change validated
  592. lpCshData->fValidLink = TRUE;
  593. }
  594. if (lpCshData->bItemNameStored && lpCshData->bFileNameStored) {
  595. HWND hListBox = GetDlgItem(lpCshData->lpOfn->hwndOwner, ID_EL_LINKSLISTBOX);
  596. DiffPrefix(
  597. lpLI->lpszDisplayName,
  598. (LPTSTR)lpCshData->szEdit,
  599. (TCHAR FAR* FAR*)&lpCshData->lpszFrom,
  600. (TCHAR FAR* FAR*)&lpCshData->lpszTo
  601. );
  602. /* we keep the strings if there is a difference between the
  603. ** lpszFrom and lpszTo strings AND if the change is only
  604. ** in the file portion otherwise free them and other
  605. ** links won't be compared.
  606. */
  607. if ( (lstrcmp(lpCshData->lpszTo, lpCshData->lpszFrom)==0)
  608. || (lstrlen(lpCshData->lpszTo)>lpCshData->nFileLength)) {
  609. if (lpCshData->lpszFrom) {
  610. OleStdFree(lpCshData->lpszFrom);
  611. lpCshData->lpszFrom = NULL;
  612. }
  613. if (lpCshData->lpszTo) {
  614. OleStdFree(lpCshData->lpszTo);
  615. lpCshData->lpszTo = NULL;
  616. }
  617. }
  618. }
  619. // Copy OUT results to original structure
  620. lpCshData->lpOCshData->lpszFrom = lpCshData->lpszFrom;
  621. lpCshData->lpOCshData->lpszTo = lpCshData->lpszTo;
  622. lpCshData->lpOCshData->fValidLink = lpCshData->fValidLink;
  623. SendMessage(hDlg, uMsgEndDialog, 0, 0L); // do cleanup
  624. return 0; // Close ChangeSource dialog
  625. }
  626. switch (uMsg) {
  627. case WM_INITDIALOG:
  628. {
  629. LPOPENFILENAME lpOfn = (LPOPENFILENAME)lParam;
  630. LPOLEUICHANGESOURCEHOOKDATA lpOCshData =
  631. (LPOLEUICHANGESOURCEHOOKDATA)lpOfn->lCustData;
  632. gh=GlobalAlloc(
  633. GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(CHANGESOURCEHOOKDATA));
  634. if (NULL==gh)
  635. {
  636. // Memory allocation error; fail to bring up dialog
  637. PostMessage(hDlg, uMsgEndDialog, 0, 0L);
  638. return 0;
  639. }
  640. lpCshData = GlobalLock(gh);
  641. SetProp(hDlg, STRUCTUREPROP, gh);
  642. lpCshData->lpOCshData = lpOCshData;
  643. lpCshData->lpOfn = lpOfn;
  644. lpLI = lpCshData->lpOCshData->lpLI;
  645. lpCshData->bFileNameStored = TRUE;
  646. lpCshData->bItemNameStored = TRUE;
  647. lpCshData->nFileLength = (int)lpLI->clenFileName;
  648. if (lpLI->lpszDisplayName) {
  649. LSTRCPYN((LPTSTR)lpCshData->szFileName, lpLI->lpszDisplayName,
  650. lpCshData->nFileLength + 1);
  651. lstrcpy((LPTSTR)lpCshData->szEdit, lpLI->lpszDisplayName);
  652. } else {
  653. lpCshData->szFileName[0] = TEXT('\0');
  654. lpCshData->szEdit[0] = TEXT('\0');
  655. }
  656. if (lpLI->lpszItemName)
  657. lstrcpy((LPTSTR)lpCshData->szItemName, lpLI->lpszItemName);
  658. else
  659. lpCshData->szItemName[0] = TEXT('\0');
  660. return 0;
  661. }
  662. case WM_COMMAND:
  663. // User pressed the CANCEL button
  664. if (wParam == IDCANCEL)
  665. {
  666. if (lpCshData->lpszFrom)
  667. {
  668. OleStdFree(lpCshData->lpszFrom);
  669. lpCshData->lpszFrom = NULL;
  670. }
  671. if (lpCshData->lpszTo)
  672. {
  673. OleStdFree(lpCshData->lpszTo);
  674. lpCshData->lpszTo = NULL;
  675. }
  676. // Copy OUT results to original structure
  677. lpCshData->lpOCshData->lpszFrom = NULL;
  678. lpCshData->lpOCshData->lpszTo = NULL;
  679. lpCshData->lpOCshData->fValidLink = FALSE;
  680. SendMessage(hDlg, uMsgEndDialog, 0, 0L); // do cleanup
  681. return 0; // Close ChangeSource dialog
  682. }
  683. if ((wParam == lst1) &&
  684. (HIWORD(lParam) == LBN_SELCHANGE)) {
  685. int nIndex;
  686. HWND hListBox = (HWND)LOWORD(lParam);
  687. static TCHAR szFileNameBuf[OLEUI_CCHPATHMAX];
  688. static TCHAR szEditBuf[OLEUI_CCHPATHMAX];
  689. nIndex = (int)SendMessage(hListBox, LB_GETCURSEL, 0, 0L);
  690. SendMessage(hListBox, LB_GETTEXT,
  691. (WPARAM)nIndex, (LPARAM)(LPTSTR)szFileNameBuf);
  692. /* need to build the full path filename for the moniker */
  693. #ifdef WIN32
  694. CharToOem(szFileNameBuf, szFileNameBuf);
  695. #else
  696. AnsiToOem(szFileNameBuf, szFileNameBuf);
  697. #endif
  698. _fullpath(szEditBuf, szFileNameBuf, sizeof(szEditBuf));
  699. #ifdef WIN32
  700. OemToChar(szEditBuf, szEditBuf);
  701. #else
  702. OemToAnsi(szEditBuf, szEditBuf);
  703. #endif
  704. /* convert filename to lower case as it appears in the
  705. ** listbox
  706. */
  707. #ifdef WIN32
  708. CharLower(szEditBuf);
  709. #else
  710. AnsiLower(szEditBuf);
  711. #endif
  712. LSTRCPYN((LPTSTR)lpCshData->szEdit, (LPTSTR)szEditBuf,
  713. sizeof(lpCshData->szEdit) / sizeof(TCHAR));
  714. LSTRCPYN((LPTSTR)lpCshData->szFileName,
  715. (LPTSTR)lpCshData->szEdit,
  716. sizeof(lpCshData->szFileName) / sizeof(TCHAR) );
  717. lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit);
  718. if (lpCshData->bItemNameStored)
  719. lstrcat((LPTSTR)lpCshData->szEdit, lpCshData->szItemName);
  720. SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szEdit);
  721. lpCshData->nEditLength = lstrlen((LPTSTR)lpCshData->szEdit);
  722. lpCshData->bFileNameStored = TRUE;
  723. return 1;
  724. }
  725. if ((wParam == lst2) &&
  726. (HIWORD(lParam) == LBN_SELCHANGE)) {
  727. if (lpCshData->bItemNameStored)
  728. SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szItemName);
  729. return 1;
  730. }
  731. if ((wParam == cmb2) &&
  732. (HIWORD(lParam) == CBN_SELCHANGE)) {
  733. if (lpCshData->bItemNameStored)
  734. SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szItemName);
  735. return 1;
  736. }
  737. if (wParam == edt1) {
  738. HWND hEdit = (HWND)LOWORD(lParam);
  739. switch (HIWORD(lParam)) {
  740. case EN_SETFOCUS:
  741. SendMessage(hEdit, EM_SETSEL, 0,
  742. MAKELPARAM(0, lpCshData->nFileLength));
  743. return 1;
  744. case EN_KILLFOCUS:
  745. if (SendMessage(hEdit, EM_GETMODIFY, 0, 0L)) {
  746. TCHAR szTmp[OLEUI_CCHPATHMAX];
  747. int nItemLength = lstrlen((LPTSTR)lpCshData->szItemName);
  748. *(LPWORD)lpCshData->szEdit = sizeof(lpCshData->szEdit)/
  749. sizeof(TCHAR) - 1;
  750. lpCshData->nEditLength = (int)SendMessage(hEdit,
  751. EM_GETLINE, 0, (LPARAM)(LPTSTR)lpCshData->szEdit);
  752. lpCshData->szEdit[lpCshData->nEditLength] = TEXT('\0');
  753. LSTRCPYN((LPTSTR)szTmp, (LPTSTR)lpCshData->szEdit,
  754. lpCshData->nFileLength + 1);
  755. if (lpCshData->bFileNameStored &&
  756. !lstrcmp((LPTSTR)lpCshData->szFileName, (LPTSTR)szTmp)) {
  757. lstrcpy((LPTSTR)lpCshData->szItemName,
  758. (LPTSTR)lpCshData->szEdit + lpCshData->nFileLength);
  759. lpCshData->bItemNameStored = TRUE;
  760. }
  761. else if (lpCshData->bItemNameStored &&
  762. !lstrcmp((LPTSTR)lpCshData->szItemName,
  763. (LPTSTR)lpCshData->szEdit +
  764. lpCshData->nEditLength -
  765. nItemLength)) {
  766. if (lpCshData->nEditLength==nItemLength) {
  767. lpCshData->bFileNameStored = FALSE;
  768. } else {
  769. LSTRCPYN((LPTSTR)lpCshData->szFileName,
  770. (LPTSTR)lpCshData->szEdit,
  771. lpCshData->nEditLength -
  772. nItemLength+1);
  773. lpCshData->bFileNameStored = TRUE;
  774. }
  775. }
  776. else {
  777. lpCshData->bItemNameStored = FALSE;
  778. lpCshData->bFileNameStored = FALSE;
  779. }
  780. SendMessage(hEdit, EM_SETMODIFY, FALSE, 0L);
  781. }
  782. return 0;
  783. }
  784. }
  785. return 0;
  786. default:
  787. return 0;
  788. }
  789. }
  790. /*
  791. * ChangeSource
  792. *
  793. * Purpose:
  794. * Displays the standard GetOpenFileName dialog with a customized template and
  795. * hook.
  796. *
  797. * Parameters:
  798. * hWndOwner HWND owning the dialog
  799. * lpszFile LPSTR specifying the initial file. If there is no
  800. * initial file the first character of this string should
  801. * be a null.
  802. * cchFile UINT length of pszFile
  803. * iFilterString UINT index into the stringtable for the filter string.
  804. * lpfnBrowseHook COMMDLGHOOKPROC hook to process link source information when user
  805. * presses OK
  806. * lpCshData LPCHANGESOURCEHOOKDATA custom data that is accessible to the hook
  807. *
  808. * Return Value:
  809. * BOOL TRUE if the user selected a file and pressed OK.
  810. * FALSE otherwise, such as on pressing Cancel.
  811. */
  812. BOOL WINAPI ChangeSource(
  813. HWND hWndOwner,
  814. LPTSTR lpszFile,
  815. UINT cchFile,
  816. UINT iFilterString,
  817. COMMDLGHOOKPROC lpfnBrowseHook,
  818. LPOLEUICHANGESOURCEHOOKDATA lpCshData
  819. )
  820. {
  821. UINT cch;
  822. TCHAR szFilters[OLEUI_CCHPATHMAX];
  823. TCHAR szDir[OLEUI_CCHPATHMAX];
  824. TCHAR szTitle[OLEUI_CCHPATHMAX];
  825. OPENFILENAME ofn;
  826. BOOL fStatus;
  827. LPTSTR lpszFileBuffer;
  828. if (NULL==lpszFile || 0==cchFile)
  829. return FALSE;
  830. lpszFileBuffer = (LPTSTR)OleStdMalloc(cchFile * sizeof(TCHAR));
  831. if (!lpszFileBuffer)
  832. return FALSE;
  833. lstrcpy(lpszFileBuffer, lpszFile);
  834. // Get filters
  835. if (0!=iFilterString)
  836. cch = LoadString(ghInst, iFilterString, (LPTSTR)szFilters,
  837. OLEUI_CCHPATHMAX);
  838. else
  839. {
  840. szFilters[0]=0;
  841. cch=1;
  842. }
  843. if (0==cch) {
  844. fStatus = FALSE;
  845. goto cleanup;
  846. }
  847. ReplaceCharWithNull(szFilters, szFilters[cch-1]);
  848. LSTRCPYN((LPTSTR)szDir, lpszFile, OLEUI_CCHPATHMAX);
  849. for (cch = lstrlen((LPTSTR)szDir) - 1; cch >= 0; cch--)
  850. {
  851. if ((szDir[cch]==TEXT('\\')) || (szDir[cch]==TEXT(':')) || (szDir[cch]==TEXT('/')))
  852. break;
  853. }
  854. if (cch < 0)
  855. cch = 0;
  856. szDir[cch] = TEXT('\0');
  857. LoadString(ghInst, IDS_CHANGESOURCE, (LPTSTR)szTitle, OLEUI_CCHPATHMAX);
  858. _fmemset((LPOPENFILENAME)&ofn, 0, sizeof(ofn));
  859. ofn.lStructSize = sizeof(ofn);
  860. ofn.hwndOwner = hWndOwner;
  861. ofn.lpstrFile = lpszFileBuffer;
  862. ofn.nMaxFile = cchFile;
  863. ofn.lpstrFilter = (LPTSTR)szFilters;
  864. ofn.nFilterIndex = 1;
  865. ofn.lpstrTitle = (LPTSTR)szTitle;
  866. ofn.lpstrInitialDir = (LPTSTR)szDir;
  867. ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEOPEN);
  868. ofn.lpfnHook = lpfnBrowseHook;
  869. ofn.hInstance = ghInst;
  870. ofn.lCustData = (LPARAM)lpCshData;
  871. ofn.Flags = OFN_NOVALIDATE | OFN_HIDEREADONLY |
  872. OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
  873. // Only show help button if edit links dialog shows it.
  874. if (lpCshData->lpEL->lpOEL->dwFlags & ELF_SHOWHELP)
  875. ofn.Flags |= OFN_SHOWHELP;
  876. fStatus = GetOpenFileName((LPOPENFILENAME)&ofn);
  877. cleanup:
  878. OleStdFree((LPVOID)lpszFileBuffer);
  879. return fStatus;
  880. }
  881. /*
  882. * Container_ChangeSource
  883. *
  884. * Purpose:
  885. * Tunnel to File Open type dlg and allow user to select new file
  886. * for file based monikers, OR to change the whole moniker to what
  887. * the user types into the editable field.
  888. *
  889. * Parameters:
  890. * hDlg HWND of the dialog
  891. * LPEDITLINKS Pointer to EditLinks structure (contains all nec.
  892. * info)
  893. *
  894. * Return Value:
  895. * BOOL for now, because we are not using any ole functions
  896. * to return an HRESULT.
  897. * HRESULT HRESULT value indicating success or failure of
  898. * changing the moniker value
  899. */
  900. BOOL Container_ChangeSource(HWND hDlg, LPEDITLINKS lpEL)
  901. {
  902. UINT uRet;
  903. int cSelItems;
  904. int FAR* rgIndex;
  905. int i = 0;
  906. LPLINKINFO lpLI;
  907. HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
  908. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  909. OLEUICHANGESOURCEHOOKDATA cshData; // Data that needs to be accessed
  910. // by the ChangeSource dialog hook
  911. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  912. if (cSelItems < 0)
  913. return FALSE;
  914. if (!cSelItems)
  915. return TRUE;
  916. if (!lpEL->fClose) {
  917. SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
  918. lpEL->fClose = TRUE;
  919. }
  920. _fmemset((LPOLEUICHANGESOURCEHOOKDATA)&cshData, 0, sizeof(cshData));
  921. cshData.cbStruct=sizeof(cshData);
  922. cshData.hWndOwner=hDlg;
  923. cshData.lpEL = (LPEDITLINKS)lpEL;
  924. cshData.lpszFrom = NULL;
  925. cshData.lpszTo = NULL;
  926. for (i = cSelItems-1; i >=0; i--) {
  927. SendMessage(hListBox, LB_GETTEXT, rgIndex[i],
  928. (LPARAM) (LPLINKINFO FAR*) &lpLI);
  929. uRet = UStandardHook(lpEL, hDlg, uMsgBrowse,
  930. OLEUI_CCHPATHMAX_SIZE, (LONG)(LPTSTR)lpLI->lpszDisplayName);
  931. if (!uRet) {
  932. cshData.lpLI = lpLI;
  933. /* Bring up the ChangeSource dialog after hooking it so
  934. ** that the user specified link source is verified
  935. ** when OK is pressed.
  936. */
  937. uRet = (UINT)ChangeSource(hDlg, lpLI->lpszDisplayName,
  938. OLEUI_CCHPATHMAX, IDS_FILTERS, ChangeSourceHook,
  939. &cshData);
  940. }
  941. /* If Cancel is pressed in any ChangeSource dialog, stop
  942. ** the ChangeSource processing for all links.
  943. */
  944. if (!uRet) {
  945. if (rgIndex)
  946. OleStdFree(rgIndex);
  947. return TRUE;
  948. }
  949. UpdateLinkLBItem(hListBox, rgIndex[i], lpEL, TRUE);
  950. if (cshData.lpszFrom && cshData.lpszTo) {
  951. ChangeAllLinks(hListBox, lpOleUILinkCntr, cshData.lpszFrom,
  952. cshData.lpszTo);
  953. OleStdFree(cshData.lpszFrom);
  954. OleStdFree(cshData.lpszTo);
  955. }
  956. } // end FOR
  957. if (rgIndex)
  958. OleStdFree(rgIndex);
  959. return TRUE;
  960. }
  961. /*
  962. * Container_AutomaticManual
  963. *
  964. * Purpose:
  965. * To change the selected moniker to manual or automatic update.
  966. *
  967. * Parameters:
  968. * hDlg HWND of the dialog
  969. * FAutoMan Flag indicating AUTO (TRUE/1) or MANUAL(FALSE/0)
  970. * LPEDITLINKS Pointer to EditLinks structure (contains all nec.
  971. * info)
  972. * * this may change - don't know how the linked list
  973. * * of multi-selected items will work.
  974. * Return Value:
  975. * HRESULT HRESULT value indicating success or failure of
  976. * changing the moniker value
  977. */
  978. HRESULT Container_AutomaticManual(HWND hDlg, BOOL fAutoMan, LPEDITLINKS lpEL)
  979. {
  980. HRESULT hErr = NOERROR;
  981. int cSelItems;
  982. int FAR* rgIndex;
  983. int i = 0;
  984. LPLINKINFO lpLI;
  985. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  986. HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
  987. BOOL bUpdate = FALSE;
  988. OleDbgAssert(lpOleUILinkCntr);
  989. /* Change so looks at flag in structure. Only update those that
  990. need to be updated. Make sure to change flag if status changes.
  991. */
  992. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  993. if (cSelItems < 0)
  994. return ResultFromScode(E_FAIL);
  995. if (!cSelItems)
  996. return NOERROR;
  997. if (!lpEL->fClose)
  998. SetDlgItemText(hDlg, IDCANCEL, (LPTSTR)lpEL->szClose);
  999. for (i = 0; i < cSelItems; i++) {
  1000. SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[i],
  1001. (LPARAM) (LPLINKINFO FAR*) &lpLI);
  1002. if (fAutoMan) { // If switching to AUTOMATIC
  1003. if (!lpLI->fIsAuto) { // Only change MANUAL links
  1004. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n"));
  1005. hErr=lpOleUILinkCntr->lpVtbl->SetLinkUpdateOptions(
  1006. lpOleUILinkCntr,
  1007. lpLI->dwLink,
  1008. OLEUPDATE_ALWAYS
  1009. );
  1010. OLEDBG_END2
  1011. lpLI->fIsAuto=TRUE;
  1012. lpLI->fIsMarked = TRUE;
  1013. bUpdate = TRUE;
  1014. }
  1015. }
  1016. else { // If switching to MANUAL
  1017. if (lpLI->fIsAuto) { // Only do AUTOMATIC Links
  1018. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n"));
  1019. hErr=lpOleUILinkCntr->lpVtbl->SetLinkUpdateOptions(
  1020. lpOleUILinkCntr,
  1021. lpLI->dwLink,
  1022. OLEUPDATE_ONCALL
  1023. );
  1024. OLEDBG_END2
  1025. lpLI->fIsAuto = FALSE;
  1026. lpLI->fIsMarked = TRUE;
  1027. bUpdate = TRUE;
  1028. }
  1029. }
  1030. if (hErr != NOERROR) {
  1031. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::SetLinkUpdateOptions returned"),hErr);
  1032. break;
  1033. }
  1034. }
  1035. if (bUpdate)
  1036. RefreshLinkLB(hListBox, lpOleUILinkCntr);
  1037. if (rgIndex)
  1038. OleStdFree((LPVOID)rgIndex);
  1039. return hErr;
  1040. }
  1041. HRESULT CancelLink(HWND hDlg, LPEDITLINKS lpEL)
  1042. {
  1043. HRESULT hErr;
  1044. LPMONIKER lpmk;
  1045. int cSelItems;
  1046. int FAR* rgIndex;
  1047. int i = 0;
  1048. LPLINKINFO lpLI;
  1049. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  1050. HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
  1051. BOOL bUpdate = FALSE;
  1052. OleDbgAssert(lpOleUILinkCntr);
  1053. lpmk = NULL;
  1054. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  1055. if (cSelItems < 0)
  1056. return ResultFromScode(E_FAIL);
  1057. if (!cSelItems)
  1058. return NOERROR;
  1059. if (!lpEL->fClose) {
  1060. SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
  1061. lpEL->fClose = TRUE;
  1062. }
  1063. for (i = 0; i < cSelItems; i++) {
  1064. SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[i],
  1065. (LPARAM)(LPLINKINFO FAR*) &lpLI);
  1066. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::CancelLink called\r\n"));
  1067. hErr = lpOleUILinkCntr->lpVtbl->CancelLink(
  1068. lpOleUILinkCntr,
  1069. lpLI->dwLink
  1070. );
  1071. OLEDBG_END2
  1072. if (hErr != NOERROR) {
  1073. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::CancelLink returned"),hErr);
  1074. lpLI->fIsMarked = TRUE;
  1075. bUpdate = TRUE;
  1076. }
  1077. else
  1078. // Delete links that we make null from listbox
  1079. SendMessage(hListBox, LB_DELETESTRING, (WPARAM) rgIndex[i], 0L);
  1080. }
  1081. if (bUpdate)
  1082. RefreshLinkLB(hListBox, lpOleUILinkCntr);
  1083. if (rgIndex)
  1084. OleStdFree((LPVOID)rgIndex);
  1085. return hErr;
  1086. }
  1087. /*
  1088. * Container_UpdateNow
  1089. *
  1090. * Purpose:
  1091. * Immediately force an update for all (manual) links
  1092. *
  1093. * Parameters:
  1094. * hDlg HWND of the dialog
  1095. * LPEDITLINKS Pointer to EditLinks structure (contains all nec. info)
  1096. * * this may change - don't know how the linked list
  1097. * * of multi-selected items will work.
  1098. * Return Value:
  1099. * HRESULT HRESULT value indicating success or failure of
  1100. * changing the moniker value
  1101. */
  1102. HRESULT Container_UpdateNow(HWND hDlg, LPEDITLINKS lpEL)
  1103. {
  1104. HRESULT hErr;
  1105. LPLINKINFO lpLI;
  1106. int cSelItems;
  1107. int FAR* rgIndex;
  1108. int i = 0;
  1109. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  1110. HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
  1111. BOOL bUpdate = FALSE;
  1112. OleDbgAssert(lpOleUILinkCntr);
  1113. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  1114. if (cSelItems < 0)
  1115. return ResultFromScode(E_FAIL);
  1116. if (!cSelItems)
  1117. return NOERROR;
  1118. if (!lpEL->fClose) {
  1119. SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
  1120. lpEL->fClose = TRUE;
  1121. }
  1122. for (i = 0; i < cSelItems; i++) {
  1123. SendMessage(hListBox, LB_GETTEXT,
  1124. (WPARAM)rgIndex[i], (LPARAM)(LPLINKINFO FAR*)&lpLI);
  1125. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::UpdateLink called\r\n"));
  1126. hErr = lpOleUILinkCntr->lpVtbl->UpdateLink(
  1127. lpOleUILinkCntr,
  1128. lpLI->dwLink,
  1129. TRUE,
  1130. FALSE
  1131. );
  1132. OLEDBG_END2
  1133. bUpdate = TRUE;
  1134. lpLI->fIsMarked = TRUE;
  1135. if (hErr != NOERROR) {
  1136. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::UpdateLink returned"),hErr);
  1137. break;
  1138. }
  1139. }
  1140. if (bUpdate)
  1141. RefreshLinkLB(hListBox, lpOleUILinkCntr);
  1142. if (rgIndex)
  1143. OleStdFree((LPVOID)rgIndex);
  1144. return hErr;
  1145. }
  1146. /*
  1147. * Container_OpenSource
  1148. *
  1149. * Purpose:
  1150. * Immediately force an update for all (manual) links
  1151. *
  1152. * Parameters:
  1153. * hDlg HWND of the dialog
  1154. * LPEDITLINKS Pointer to EditLinks structure (contains all nec.
  1155. * info)
  1156. *
  1157. * Return Value:
  1158. * HRESULT HRESULT value indicating success or failure of
  1159. * changing the moniker value
  1160. */
  1161. HRESULT Container_OpenSource(HWND hDlg, LPEDITLINKS lpEL)
  1162. {
  1163. HRESULT hErr;
  1164. int cSelItems;
  1165. int FAR* rgIndex;
  1166. LPLINKINFO lpLI;
  1167. RECT rcPosRect;
  1168. LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  1169. HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
  1170. OleDbgAssert(lpOleUILinkCntr);
  1171. rcPosRect.top = 0;
  1172. rcPosRect.left = 0;
  1173. rcPosRect.right = 0;
  1174. rcPosRect.bottom = 0;
  1175. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  1176. if (cSelItems < 0)
  1177. return ResultFromScode(E_FAIL);
  1178. if (cSelItems != 1) // can't open source for multiple items
  1179. return NOERROR;
  1180. if (!lpEL->fClose) {
  1181. SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
  1182. lpEL->fClose = TRUE;
  1183. }
  1184. SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[0],
  1185. (LPARAM)(LPLINKINFO FAR*)&lpLI);
  1186. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::OpenLinkSource called\r\n"));
  1187. hErr = lpOleUILinkCntr->lpVtbl->OpenLinkSource(
  1188. lpOleUILinkCntr,
  1189. lpLI->dwLink
  1190. );
  1191. OLEDBG_END2
  1192. UpdateLinkLBItem(hListBox, rgIndex[0], lpEL, TRUE);
  1193. if (hErr != NOERROR)
  1194. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::OpenLinkSource returned"),hErr);
  1195. if (rgIndex)
  1196. OleStdFree((LPVOID)rgIndex);
  1197. return hErr;
  1198. }
  1199. /* AddLinkLBItem
  1200. ** -------------
  1201. **
  1202. ** Add the item pointed to by lpLI to the Link ListBox and return
  1203. ** the index of it in the ListBox
  1204. */
  1205. int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI, BOOL fGetSelected)
  1206. {
  1207. HRESULT hErr;
  1208. DWORD dwUpdateOpt;
  1209. int nIndex;
  1210. OleDbgAssert(lpOleUILinkCntr && hListBox && lpLI);
  1211. lpLI->fDontFree = FALSE;
  1212. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkSource called\r\n"));
  1213. hErr = lpOleUILinkCntr->lpVtbl->GetLinkSource(
  1214. lpOleUILinkCntr,
  1215. lpLI->dwLink,
  1216. (LPTSTR FAR*)&lpLI->lpszDisplayName,
  1217. (ULONG FAR*)&lpLI->clenFileName,
  1218. (LPTSTR FAR*)&lpLI->lpszFullLinkType,
  1219. (LPTSTR FAR*)&lpLI->lpszShortLinkType,
  1220. (BOOL FAR*)&lpLI->fSourceAvailable,
  1221. fGetSelected ? (BOOL FAR*)&lpLI->fIsSelected : NULL
  1222. );
  1223. OLEDBG_END2
  1224. if (hErr != NOERROR) {
  1225. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkSource returned"),hErr);
  1226. PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKSOURCE,
  1227. MB_ICONEXCLAMATION | MB_OK);
  1228. goto cleanup;
  1229. }
  1230. OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkUpdateOptions called\r\n"));
  1231. hErr=lpOleUILinkCntr->lpVtbl->GetLinkUpdateOptions(
  1232. lpOleUILinkCntr,
  1233. lpLI->dwLink,
  1234. (LPDWORD)&dwUpdateOpt
  1235. );
  1236. OLEDBG_END2
  1237. if (hErr != NOERROR) {
  1238. OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkUpdateOptions returned"),hErr);
  1239. PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKUPDATEOPTIONS,
  1240. MB_ICONEXCLAMATION | MB_OK);
  1241. goto cleanup;
  1242. }
  1243. if (lpLI->fSourceAvailable) {
  1244. if (dwUpdateOpt == OLEUPDATE_ALWAYS) {
  1245. lpLI->fIsAuto = TRUE;
  1246. LoadString(ghInst, IDS_LINK_AUTO, lpLI->lpszAMX,
  1247. (int)OleStdGetSize((LPVOID)lpLI->lpszAMX));
  1248. }
  1249. else {
  1250. lpLI->fIsAuto = FALSE;
  1251. LoadString(ghInst, IDS_LINK_MANUAL, lpLI->lpszAMX,
  1252. (int)OleStdGetSize((LPVOID)lpLI->lpszAMX));
  1253. }
  1254. }
  1255. else
  1256. LoadString(ghInst, IDS_LINK_UNKNOWN, lpLI->lpszAMX,
  1257. (int)OleStdGetSize((LPVOID)lpLI->lpszAMX));
  1258. BreakString(lpLI);
  1259. nIndex = (int)SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0,
  1260. (LPARAM)(DWORD)lpLI);
  1261. if (nIndex == LB_ERR) {
  1262. PopupMessage(hListBox, IDS_LINKS, IDS_ERR_ADDSTRING,
  1263. MB_ICONEXCLAMATION | MB_OK);
  1264. goto cleanup;
  1265. }
  1266. return nIndex;
  1267. cleanup:
  1268. if (lpLI->lpszDisplayName)
  1269. OleStdFree((LPVOID)lpLI->lpszDisplayName);
  1270. if (lpLI->lpszShortLinkType)
  1271. OleStdFree((LPVOID)lpLI->lpszShortLinkType);
  1272. if (lpLI->lpszFullLinkType)
  1273. OleStdFree((LPVOID)lpLI->lpszFullLinkType);
  1274. return -1;
  1275. }
  1276. /* BreakString
  1277. * -----------
  1278. *
  1279. * Purpose:
  1280. * Break the lpszDisplayName into various parts
  1281. *
  1282. * Parameters:
  1283. * lpLI pointer to LINKINFO structure
  1284. *
  1285. * Returns:
  1286. *
  1287. */
  1288. VOID BreakString(LPLINKINFO lpLI)
  1289. {
  1290. LPTSTR lpsz;
  1291. if (!lpLI->clenFileName ||
  1292. (lstrlen(lpLI->lpszDisplayName)==(int)lpLI->clenFileName)) {
  1293. lpLI->lpszItemName = NULL;
  1294. }
  1295. else {
  1296. lpLI->lpszItemName = lpLI->lpszDisplayName + lpLI->clenFileName;
  1297. }
  1298. // search from last character of filename
  1299. lpsz = lpLI->lpszDisplayName + lstrlen(lpLI->lpszDisplayName);
  1300. while (lpsz > lpLI->lpszDisplayName) {
  1301. #ifdef WIN32
  1302. // AnsiPrev is obsolete in Win32
  1303. lpsz = CharPrev(lpLI->lpszDisplayName, lpsz);
  1304. #else
  1305. lpsz = AnsiPrev(lpLI->lpszDisplayName, lpsz);
  1306. #endif
  1307. if ((*lpsz == TEXT('\\')) || (*lpsz == TEXT('/')) || (*lpsz == TEXT(':')))
  1308. break;
  1309. }
  1310. if (lpsz == lpLI->lpszDisplayName)
  1311. lpLI->lpszShortFileName = lpsz;
  1312. else
  1313. #ifdef WIN32
  1314. // AnsiNext is obsolete in Win32
  1315. lpLI->lpszShortFileName = CharNext(lpsz);
  1316. #else
  1317. lpLI->lpszShortFileName = AnsiNext(lpsz);
  1318. #endif
  1319. }
  1320. /* GetSelectedItems
  1321. * ----------------
  1322. *
  1323. * Purpose:
  1324. * Retrieve the indices of the selected items in the listbox
  1325. * Note that *lprgIndex needed to be free after using the function
  1326. *
  1327. * Parameters:
  1328. * hListBox window handle of listbox
  1329. * lprgIndex pointer to an integer array to receive the indices
  1330. * must be freed afterwards
  1331. *
  1332. * Returns:
  1333. * number of indices retrieved, -1 if error
  1334. */
  1335. int GetSelectedItems(HWND hListBox, int FAR* FAR* lprgIndex)
  1336. {
  1337. DWORD cSelItems;
  1338. DWORD cCheckItems;
  1339. *lprgIndex = NULL;
  1340. cSelItems = SendMessage(hListBox, LB_GETSELCOUNT, 0, 0L);
  1341. if (cSelItems < 0) // error
  1342. return (int)cSelItems;
  1343. if (!cSelItems)
  1344. return 0;
  1345. *lprgIndex = (int FAR*)OleStdMalloc((int)cSelItems * sizeof(int));
  1346. cCheckItems = SendMessage(hListBox, LB_GETSELITEMS,
  1347. (WPARAM) cSelItems, (LPARAM) (int FAR*) *lprgIndex);
  1348. if (cCheckItems == cSelItems)
  1349. return (int)cSelItems;
  1350. else {
  1351. if (*lprgIndex)
  1352. OleStdFree((LPVOID)*lprgIndex);
  1353. *lprgIndex = NULL;
  1354. return 0;
  1355. }
  1356. }
  1357. /* InitControls
  1358. * ------------
  1359. *
  1360. * Purpose:
  1361. * Initialize the state of the Auto/Manual button, Link source/type
  1362. * static field, etc in the dialogs according to the selection in the
  1363. * listbox
  1364. *
  1365. * Parameters:
  1366. * hDlg handle to the dialog window
  1367. */
  1368. VOID InitControls(HWND hDlg, LPEDITLINKS lpEL)
  1369. {
  1370. int cSelItems;
  1371. HWND hListBox;
  1372. int i;
  1373. int FAR* rgIndex;
  1374. LPLINKINFO lpLI;
  1375. LPTSTR lpszType = NULL;
  1376. LPTSTR lpszSource = NULL;
  1377. int cAuto = 0;
  1378. int cManual = 0;
  1379. BOOL bSameType = TRUE;
  1380. BOOL bSameSource = TRUE;
  1381. TCHAR tsz[OLEUI_CCHPATHMAX];
  1382. LPTSTR lpsz;
  1383. hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
  1384. cSelItems = GetSelectedItems(hListBox, &rgIndex);
  1385. if (cSelItems < 0)
  1386. return;
  1387. EnableWindow(GetDlgItem(hDlg, ID_EL_AUTOMATIC), (BOOL)cSelItems);
  1388. EnableWindow(GetDlgItem(hDlg, ID_EL_MANUAL), (BOOL)cSelItems);
  1389. if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK))
  1390. EnableWindow(GetDlgItem(hDlg, ID_EL_CANCELLINK), (BOOL)cSelItems);
  1391. if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE))
  1392. EnableWindow(GetDlgItem(hDlg, ID_EL_OPENSOURCE), cSelItems == 1);
  1393. if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE))
  1394. EnableWindow(GetDlgItem(hDlg, ID_EL_CHANGESOURCE), cSelItems == 1);
  1395. if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW))
  1396. EnableWindow(GetDlgItem(hDlg, ID_EL_UPDATENOW), (BOOL)cSelItems);
  1397. for (i = 0; i < cSelItems; i++) {
  1398. SendDlgItemMessage(
  1399. hDlg,
  1400. ID_EL_LINKSLISTBOX,
  1401. LB_GETTEXT,
  1402. (WPARAM)rgIndex[i],
  1403. (LPARAM)(LPLINKINFO FAR*)&lpLI);
  1404. if (lpszSource && lpLI->lpszDisplayName) {
  1405. if (bSameSource && lstrcmp(lpszSource, lpLI->lpszDisplayName)) {
  1406. bSameSource = FALSE;
  1407. }
  1408. }
  1409. else
  1410. lpszSource = lpLI->lpszDisplayName;
  1411. if (lpszType && lpLI->lpszFullLinkType) {
  1412. if (bSameType && lstrcmp(lpszType, lpLI->lpszFullLinkType)) {
  1413. bSameType = FALSE;
  1414. }
  1415. }
  1416. else
  1417. lpszType = lpLI->lpszFullLinkType;
  1418. if (lpLI->fIsAuto)
  1419. cAuto++;
  1420. else
  1421. cManual++;
  1422. }
  1423. CheckDlgButton(hDlg, ID_EL_AUTOMATIC, cAuto && !cManual);
  1424. CheckDlgButton(hDlg, ID_EL_MANUAL, !cAuto && cManual);
  1425. /* fill full source in static text box
  1426. ** below list
  1427. */
  1428. if (!bSameSource || !lpszSource)
  1429. lpszSource = szNULL;
  1430. lstrcpy((LPTSTR)tsz, lpszSource);
  1431. lpsz = ChopText(GetDlgItem(hDlg, ID_EL_LINKSOURCE), 0, tsz);
  1432. SetDlgItemText(hDlg, ID_EL_LINKSOURCE, lpsz);
  1433. /* fill full link type name in static
  1434. ** "type" text box
  1435. */
  1436. if (!bSameType || !lpszType)
  1437. lpszType = szNULL;
  1438. SetDlgItemText(hDlg, ID_EL_LINKTYPE, lpszType);
  1439. if (rgIndex)
  1440. OleStdFree((LPVOID)rgIndex);
  1441. }
  1442. /* UpdateLinkLBItem
  1443. * -----------------
  1444. *
  1445. * Purpose:
  1446. * Update the linkinfo struct in the listbox to reflect the changes
  1447. * made by the last operation. It is done simply by removing the item
  1448. * from the listbox and add it back.
  1449. *
  1450. * Parameters:
  1451. * hListBox handle of listbox
  1452. * nIndex index of listbox item
  1453. * lpEL pointer to editlinks structure
  1454. * bSelect select the item or not after update
  1455. */
  1456. VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect)
  1457. {
  1458. LPLINKINFO lpLI;
  1459. DWORD dwErr;
  1460. LPOLEUILINKCONTAINER lpOleUILinkCntr;
  1461. if (!hListBox || (nIndex < 0) || !lpEL)
  1462. return;
  1463. lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
  1464. dwErr = SendMessage(hListBox, LB_GETTEXT, nIndex,
  1465. (LPARAM)(LPLINKINFO FAR*) &lpLI);
  1466. if ((dwErr == LB_ERR) || !lpLI)
  1467. return;
  1468. /* Don't free the data associated with this listbox item
  1469. ** because we are going to reuse the allocated space for
  1470. ** the modified link. WM_DELETEITEM processing in the
  1471. ** dialog checks this flag before deleting data
  1472. ** associcated with list item.
  1473. */
  1474. lpLI->fDontFree = TRUE;
  1475. SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L);
  1476. nIndex = AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE);
  1477. if (bSelect) {
  1478. SendMessage(hListBox, LB_SETSEL, (WPARAM)TRUE, MAKELPARAM(nIndex, 0));
  1479. SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, MAKELPARAM(TRUE, 0));
  1480. }
  1481. }
  1482. /* DiffPrefix
  1483. * ----------
  1484. *
  1485. * Purpose:
  1486. * Compare (case-insensitive) two strings and return the prefixes of the
  1487. * the strings formed by removing the common suffix string from them.
  1488. * Integrity of tokens (directory name, filename and object names) are
  1489. * preserved. Note that the prefixes are converted to upper case
  1490. * characters.
  1491. *
  1492. * Parameters:
  1493. * lpsz1 string 1
  1494. * lpsz2 string 2
  1495. * lplpszPrefix1 prefix of string 1
  1496. * lplpszPrefix2 prefix of string 2
  1497. *
  1498. * Returns:
  1499. *
  1500. */
  1501. VOID DiffPrefix(LPCTSTR lpsz1, LPCTSTR lpsz2, TCHAR FAR* FAR* lplpszPrefix1, TCHAR FAR* FAR* lplpszPrefix2)
  1502. {
  1503. LPTSTR lpstr1;
  1504. LPTSTR lpstr2;
  1505. OleDbgAssert(lpsz1 && lpsz2 && *lpsz1 && *lpsz2 && lplpszPrefix1 &&
  1506. lplpszPrefix2);
  1507. *lplpszPrefix1 = NULL;
  1508. *lplpszPrefix2 = NULL;
  1509. #ifdef WIN32
  1510. *lplpszPrefix1 = OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(TCHAR));
  1511. #else
  1512. *lplpszPrefix1 = OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(BYTE));
  1513. #endif
  1514. if (!*lplpszPrefix1)
  1515. return;
  1516. #ifdef WIN32
  1517. *lplpszPrefix2 = OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(TCHAR));
  1518. #else
  1519. *lplpszPrefix2 = OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(BYTE));
  1520. #endif
  1521. if (!*lplpszPrefix2) {
  1522. OleStdFree(*lplpszPrefix1);
  1523. *lplpszPrefix1 = NULL;
  1524. return;
  1525. }
  1526. lstrcpy(*lplpszPrefix1, lpsz1);
  1527. lstrcpy(*lplpszPrefix2, lpsz2);
  1528. // AnsiLower(*lplpszPrefix1);
  1529. // AnsiLower(*lplpszPrefix2);
  1530. lpstr1 = *lplpszPrefix1 + lstrlen(*lplpszPrefix1);
  1531. lpstr2 = *lplpszPrefix2 + lstrlen(*lplpszPrefix2);
  1532. while ((lpstr1>*lplpszPrefix1) && (lpstr2>*lplpszPrefix2)) {
  1533. #ifdef WIN32
  1534. lpstr1 = CharPrev(*lplpszPrefix1, lpstr1);
  1535. lpstr2 = CharPrev(*lplpszPrefix2, lpstr2);
  1536. #else
  1537. lpstr1 = AnsiPrev(*lplpszPrefix1, lpstr1);
  1538. lpstr2 = AnsiPrev(*lplpszPrefix2, lpstr2);
  1539. #endif
  1540. if (*lpstr1 != *lpstr2) {
  1541. #ifdef WIN32
  1542. // AnsiNext is obsolete in Win32
  1543. lpstr1 = CharNext(lpstr1);
  1544. lpstr2 = CharNext(lpstr2);
  1545. #else
  1546. lpstr1 = AnsiNext(lpstr1);
  1547. lpstr2 = AnsiNext(lpstr2);
  1548. #endif
  1549. break;
  1550. }
  1551. }
  1552. for (; *lpstr1 && *lpstr1!=TEXT('\\') && *lpstr1!=TEXT('!');
  1553. #ifdef WIN32
  1554. lpstr1=CharNext(lpstr1));
  1555. #else
  1556. lpstr1=AnsiNext(lpstr1));
  1557. #endif
  1558. for (; *lpstr2 && *lpstr2!=TEXT('\\') && *lpstr2!=TEXT('!');
  1559. #ifdef WIN32
  1560. lpstr2=CharNext(lpstr2));
  1561. #else
  1562. lpstr2=AnsiNext(lpstr2));
  1563. #endif
  1564. *lpstr1 = TEXT('\0');
  1565. *lpstr2 = TEXT('\0');
  1566. }
  1567. /* PopupMessage
  1568. * ------------
  1569. *
  1570. * Purpose:
  1571. * Popup s messagebox and get some response from the user. It is the same
  1572. * as MessageBox() except that the title and message string are loaded
  1573. * from the resource file.
  1574. *
  1575. * Parameters:
  1576. * hwndParent parent window of message box
  1577. * idTitle id of title string
  1578. * idMessage id of message string
  1579. * fuStyle style of message box
  1580. */
  1581. int PopupMessage(HWND hwndParent, UINT idTitle, UINT idMessage, UINT fuStyle)
  1582. {
  1583. TCHAR szTitle[256];
  1584. TCHAR szMsg[256];
  1585. LoadString(ghInst, idTitle, (LPTSTR)szTitle, sizeof(szTitle)/sizeof(TCHAR));
  1586. LoadString(ghInst, idMessage, (LPTSTR)szMsg, sizeof(szMsg)/sizeof(TCHAR));
  1587. return MessageBox(hwndParent, szMsg, szTitle, fuStyle);
  1588. }
  1589. /* ChangeAllLinks
  1590. * --------------
  1591. *
  1592. * Purpose:
  1593. * Enumerate all the links in the listbox and change those starting
  1594. * with lpszFrom to lpszTo.
  1595. *
  1596. * Parameters:
  1597. * hListBox window handle of
  1598. * lpOleUILinkCntr pointer to OleUI Link Container
  1599. * lpszFrom prefix for matching
  1600. * lpszTo prefix to substitution
  1601. *
  1602. * Returns:
  1603. */
  1604. VOID ChangeAllLinks(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo)
  1605. {
  1606. int cItems;
  1607. int nIndex;
  1608. int cFrom;
  1609. LPLINKINFO lpLI;
  1610. LPTSTR szTmp[OLEUI_CCHPATHMAX];
  1611. BOOL bFound;
  1612. cFrom = lstrlen(lpszFrom);
  1613. cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L);
  1614. OleDbgAssert(cItems >= 0);
  1615. bFound = FALSE;
  1616. OleDbgPrint(3, TEXT("From : "), lpszFrom, 0);
  1617. OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0);
  1618. OleDbgPrint(3, TEXT("To : "), lpszTo, 0);
  1619. OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0);
  1620. for (nIndex=0; nIndex<cItems; nIndex++) {
  1621. SendMessage(hListBox, LB_GETTEXT, nIndex,
  1622. (LPARAM)(LPLINKINFO FAR*)&lpLI);
  1623. // unmark the item
  1624. lpLI->fIsMarked = FALSE;
  1625. /* if the corresponding position for the end of lpszFrom in the
  1626. ** display name is not a separator. We stop comparing this
  1627. ** link.
  1628. */
  1629. if (!*(lpLI->lpszDisplayName + cFrom) ||
  1630. (*(lpLI->lpszDisplayName + cFrom) == TEXT('\\')) ||
  1631. (*(lpLI->lpszDisplayName + cFrom) == TEXT('!'))) {
  1632. LSTRCPYN((LPTSTR)szTmp, lpLI->lpszDisplayName, cFrom + 1);
  1633. if (!lstrcmp((LPTSTR)szTmp, lpszFrom)) {
  1634. HRESULT hErr;
  1635. int nFileLength;
  1636. ULONG ulDummy;
  1637. if (!bFound) {
  1638. TCHAR szTitle[256];
  1639. TCHAR szMsg[256];
  1640. TCHAR szBuf[256];
  1641. int uRet;
  1642. LoadString(ghInst, IDS_CHANGESOURCE, (LPTSTR)szTitle,
  1643. sizeof(szTitle)/sizeof(TCHAR));
  1644. LoadString(ghInst, IDS_CHANGEADDITIONALLINKS,
  1645. (LPTSTR)szMsg, sizeof(szMsg)/sizeof(TCHAR));
  1646. wsprintf((LPTSTR)szBuf, (LPTSTR)szMsg, lpszFrom);
  1647. uRet = MessageBox(hListBox, (LPTSTR)szBuf, (LPTSTR)szTitle,
  1648. MB_ICONQUESTION | MB_YESNO);
  1649. if (uRet == IDYES)
  1650. bFound = TRUE;
  1651. else
  1652. return; // exit function
  1653. }
  1654. lstrcpy((LPTSTR)szTmp, lpszTo);
  1655. lstrcat((LPTSTR)szTmp, lpLI->lpszDisplayName + cFrom);
  1656. nFileLength = lstrlen((LPTSTR)szTmp) -
  1657. (lpLI->lpszItemName ? lstrlen(lpLI->lpszItemName) : 0);
  1658. hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource(
  1659. lpOleUILinkCntr,
  1660. lpLI->dwLink,
  1661. (LPTSTR)szTmp,
  1662. (ULONG)nFileLength,
  1663. (ULONG FAR*)&ulDummy,
  1664. TRUE
  1665. );
  1666. if (hErr != NOERROR)
  1667. lpOleUILinkCntr->lpVtbl->SetLinkSource(
  1668. lpOleUILinkCntr,
  1669. lpLI->dwLink,
  1670. (LPTSTR)szTmp,
  1671. (ULONG)nFileLength,
  1672. (ULONG FAR*)&ulDummy,
  1673. FALSE
  1674. );
  1675. lpLI->fIsMarked = TRUE;
  1676. }
  1677. }
  1678. }
  1679. /* have to do the refreshing after processing all links, otherwise
  1680. ** the item positions will change during the process as the
  1681. ** listbox stores items in order
  1682. */
  1683. if (bFound)
  1684. RefreshLinkLB(hListBox, lpOleUILinkCntr);
  1685. }
  1686. /* LoadLinkLB
  1687. * ----------
  1688. *
  1689. * Purpose:
  1690. * Enumerate all links from the Link Container and build up the Link
  1691. * ListBox
  1692. *
  1693. * Parameters:
  1694. * hListBox window handle of
  1695. * lpOleUILinkCntr pointer to OleUI Link Container
  1696. * lpszFrom prefix for matching
  1697. * lpszTo prefix to substitution
  1698. *
  1699. * Returns:
  1700. * number of link items loaded, -1 if error
  1701. */
  1702. int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr)
  1703. {
  1704. DWORD dwLink = 0;
  1705. LPLINKINFO lpLI;
  1706. int nIndex;
  1707. int cLinks;
  1708. cLinks = 0;
  1709. while ((dwLink = lpOleUILinkCntr->lpVtbl->GetNextLink(lpOleUILinkCntr,
  1710. dwLink)) != 0) {
  1711. lpLI = (LPLINKINFO)OleStdMalloc(sizeof(LINKINFO));
  1712. if (NULL == lpLI)
  1713. return -1;
  1714. lpLI->fIsMarked = FALSE;
  1715. lpLI->fIsSelected = FALSE;
  1716. lpLI->fDontFree = FALSE;
  1717. #ifdef WIN32
  1718. lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(TCHAR));
  1719. #else
  1720. lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(BYTE));
  1721. #endif
  1722. lpLI->dwLink = dwLink;
  1723. cLinks++;
  1724. if ((nIndex = AddLinkLBItem(hListBox,lpOleUILinkCntr,lpLI,TRUE)) < 0)
  1725. // can't load list box
  1726. return -1;
  1727. if (lpLI->fIsSelected) {
  1728. SendMessage(hListBox, LB_SETSEL, TRUE, MAKELPARAM(nIndex, 0));
  1729. }
  1730. }
  1731. if (SendMessage(hListBox,LB_GETSELITEMS,(WPARAM)1,(LPARAM)(int FAR*)&nIndex))
  1732. SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, MAKELPARAM(TRUE, 0));
  1733. return cLinks;
  1734. }
  1735. /* RefreshLinkLB
  1736. * -------------
  1737. *
  1738. * Purpose:
  1739. * Enumerate all items in the links listbox and update those with
  1740. * fIsMarked set.
  1741. * Note that this is a time consuming routine as it keeps iterating
  1742. * all items in the listbox until all of them are unmarked.
  1743. *
  1744. * Parameters:
  1745. * hListBox window handle of listbox
  1746. * lpOleUILinkCntr pointer to OleUI Link Container
  1747. *
  1748. * Returns:
  1749. *
  1750. */
  1751. VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr)
  1752. {
  1753. int cItems;
  1754. int nIndex;
  1755. LPLINKINFO lpLI;
  1756. BOOL bStop;
  1757. OleDbgAssert(hListBox);
  1758. cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L);
  1759. OleDbgAssert(cItems >= 0);
  1760. do {
  1761. bStop = TRUE;
  1762. for (nIndex=0; nIndex<cItems; nIndex++) {
  1763. SendMessage(hListBox, LB_GETTEXT, nIndex,
  1764. (LPARAM)(LPLINKINFO FAR*)&lpLI);
  1765. if (lpLI->fIsMarked) {
  1766. lpLI->fIsMarked = FALSE;
  1767. lpLI->fDontFree = TRUE;
  1768. SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L);
  1769. nIndex=AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE);
  1770. if (lpLI->fIsSelected) {
  1771. SendMessage(hListBox, LB_SETSEL, (WPARAM)TRUE,
  1772. MAKELPARAM(nIndex, 0));
  1773. SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex,
  1774. MAKELPARAM(TRUE, 0));
  1775. }
  1776. bStop = FALSE;
  1777. break;
  1778. }
  1779. }
  1780. } while (!bStop);
  1781. }
  1782.