Leaked source code of windows server 2003
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.

1855 lines
80 KiB

  1. /*
  2. * PASTESPL.CPP
  3. *
  4. * Implements the OleUIPasteSpecial function which invokes the complete
  5. * Paste Special dialog.
  6. *
  7. * Copyright (c)1992 Microsoft Corporation, All Rights Reserved
  8. */
  9. #include "precomp.h"
  10. #include "common.h"
  11. #include "utility.h"
  12. #include "resimage.h"
  13. #include "iconbox.h"
  14. #include "strsafe.h"
  15. #include <stdlib.h>
  16. OLEDBGDATA
  17. // Length of buffers to hold the strings 'Unknown Type', Unknown Source'
  18. // and 'the application which created it'
  19. // Extra long to allow room for localization.
  20. #define PS_UNKNOWNSTRLEN 200
  21. #define PS_UNKNOWNNAMELEN 256
  22. // Property label used to store clipboard viewer chain information
  23. #define NEXTCBVIEWER TEXT("NextCBViewer")
  24. // Internally used structure
  25. typedef struct tagPASTESPECIAL
  26. {
  27. // Keep this item first as the Standard* functions depend on it here.
  28. LPOLEUIPASTESPECIAL lpOPS; //Original structure passed.
  29. UINT nIDD; // IDD of dialog (used for help info)
  30. /*
  31. * What we store extra in this structure besides the original caller's
  32. * pointer are those fields that we need to modify during the life of
  33. * the dialog but that we don't want to change in the original structure
  34. * until the user presses OK.
  35. */
  36. DWORD dwFlags; // Local copy of paste special flags
  37. int nPasteListCurSel; // Save the selection the user made last
  38. int nPasteLinkListCurSel; // in the paste and pastelink lists
  39. int nSelectedIndex; // Index in arrPasteEntries[] corresponding to user selection
  40. BOOL fLink; // Indicates if Paste or PasteLink was selected by user
  41. HGLOBAL hBuff; // Scratch Buffer for building up strings
  42. TCHAR szUnknownType[PS_UNKNOWNSTRLEN]; // Buffer for 'Unknown Type' string
  43. TCHAR szUnknownSource[PS_UNKNOWNSTRLEN]; // Buffer for 'Unknown Source' string
  44. TCHAR szAppName[OLEUI_CCHKEYMAX]; // Application name of Source. Used in the result text
  45. // when Paste is selected. Obtained using clsidOD.
  46. // Information obtained from OBJECTDESCRIPTOR. This information is accessed when the Paste
  47. // radio button is selected.
  48. CLSID clsidOD; // ClassID of source
  49. SIZEL sizelOD; // sizel transfered in
  50. // ObjectDescriptor
  51. TCHAR szFullUserTypeNameOD[PS_UNKNOWNNAMELEN]; // Full User Type Name
  52. TCHAR szSourceOfDataOD[PS_UNKNOWNNAMELEN]; // Source of Data
  53. BOOL fSrcAspectIconOD; // Does Source specify DVASPECT_ICON?
  54. BOOL fSrcOnlyIconicOD; // Does Source specify OLEMISC_ONLYICONIC?
  55. HGLOBAL hMetaPictOD; // Metafile containing icon and icon title
  56. HGLOBAL hObjDesc; // Handle to OBJECTDESCRIPTOR structure from which the
  57. // above information is obtained
  58. // Information obtained from LINKSRCDESCRIPTOR. This infomation is accessed when the PasteLink
  59. // radio button is selected.
  60. CLSID clsidLSD; // ClassID of source
  61. SIZEL sizelLSD; // sizel transfered in
  62. // LinkSrcDescriptor
  63. TCHAR szFullUserTypeNameLSD[PS_UNKNOWNNAMELEN];// Full User Type Name
  64. TCHAR szSourceOfDataLSD[PS_UNKNOWNNAMELEN]; // Source of Data
  65. BOOL fSrcAspectIconLSD; // Does Source specify DVASPECT_ICON?
  66. BOOL fSrcOnlyIconicLSD; // Does Source specify OLEMISC_ONLYICONIC?
  67. HGLOBAL hMetaPictLSD; // Metafile containing icon and icon title
  68. HGLOBAL hLinkSrcDesc; // Handle to LINKSRCDESCRIPTOR structure from which the
  69. // above information is obtained
  70. BOOL fClipboardChanged; // Has clipboard content changed
  71. // if so bring down dlg after
  72. // ChangeIcon dlg returns.
  73. } PASTESPECIAL, *PPASTESPECIAL, FAR *LPPASTESPECIAL;
  74. // Data corresponding to each list item. A pointer to this structure is attached to each
  75. // Paste\PasteLink list box item using LB_SETITEMDATA
  76. typedef struct tagPASTELISTITEMDATA
  77. {
  78. int nPasteEntriesIndex; // Index of arrPasteEntries[] corresponding to list item
  79. BOOL fCntrEnableIcon; // Does calling application (called container here)
  80. // specify OLEUIPASTE_ENABLEICON for this item?
  81. } PASTELISTITEMDATA, *PPASTELISTITEMDATA, FAR *LPPASTELISTITEMDATA;
  82. // Internal function prototypes
  83. // PASTESPL.CPP
  84. INT_PTR CALLBACK PasteSpecialDialogProc(HWND, UINT, WPARAM, LPARAM);
  85. BOOL FPasteSpecialInit(HWND hDlg, WPARAM, LPARAM);
  86. BOOL FTogglePasteType(HWND, LPPASTESPECIAL, DWORD);
  87. void ChangeListSelection(HWND, LPPASTESPECIAL, HWND);
  88. void EnableDisplayAsIcon(HWND, LPPASTESPECIAL);
  89. void ToggleDisplayAsIcon(HWND, LPPASTESPECIAL);
  90. void ChangeIcon(HWND, LPPASTESPECIAL);
  91. void SetPasteSpecialHelpResults(HWND, LPPASTESPECIAL);
  92. BOOL FAddPasteListItem(HWND, BOOL, int, LPPASTESPECIAL, LPTSTR, UINT, LPTSTR);
  93. BOOL FFillPasteList(HWND, LPPASTESPECIAL);
  94. BOOL FFillPasteLinkList(HWND, LPPASTESPECIAL);
  95. BOOL FHasPercentS(LPCTSTR, LPPASTESPECIAL);
  96. HGLOBAL AllocateScratchMem(LPPASTESPECIAL);
  97. void FreeListData(HWND);
  98. BOOL FPasteSpecialReInit(HWND hDlg, LPPASTESPECIAL lpPS);
  99. /*
  100. * OleUIPasteSpecial
  101. *
  102. * Purpose:
  103. * Invokes the standard OLE Paste Special dialog box which allows the user
  104. * to select the format of the clipboard object to be pasted or paste linked.
  105. *
  106. * Parameters:
  107. * lpPS LPOLEUIPasteSpecial pointing to the in-out structure
  108. * for this dialog.
  109. *
  110. * Return Value:
  111. * UINT One of the following codes or one of the standard error codes (OLEUI_ERR_*)
  112. * defined in OLEDLG.H, indicating success or error:
  113. * OLEUI_OK User selected OK
  114. * OLEUI_CANCEL User cancelled the dialog
  115. * OLEUI_IOERR_SRCDATAOBJECTINVALID lpSrcDataObject field of OLEUIPASTESPECIAL invalid
  116. * OLEUI_IOERR_ARRPASTEENTRIESINVALID arrPasteEntries field of OLEUIPASTESPECIAL invalid
  117. * OLEUI_IOERR_ARRLINKTYPESINVALID arrLinkTypes field of OLEUIPASTESPECIAL invalid
  118. * OLEUI_PSERR_CLIPBOARDCHANGED Clipboard contents changed while dialog was up
  119. */
  120. STDAPI_(UINT) OleUIPasteSpecial(LPOLEUIPASTESPECIAL lpPS)
  121. {
  122. UINT uRet;
  123. HGLOBAL hMemDlg=NULL;
  124. uRet = UStandardValidation((LPOLEUISTANDARD)lpPS, sizeof(OLEUIPASTESPECIAL),
  125. &hMemDlg);
  126. if (uRet != OLEUI_SUCCESS)
  127. return uRet;
  128. // Validate PasteSpecial specific fields
  129. if (NULL != lpPS->lpSrcDataObj && IsBadReadPtr(lpPS->lpSrcDataObj, sizeof(IDataObject)))
  130. {
  131. uRet = OLEUI_IOERR_SRCDATAOBJECTINVALID;
  132. }
  133. if (NULL == lpPS->arrPasteEntries ||
  134. IsBadReadPtr(lpPS->arrPasteEntries, lpPS->cPasteEntries * sizeof(OLEUIPASTEENTRY)))
  135. {
  136. uRet = OLEUI_IOERR_ARRPASTEENTRIESINVALID;
  137. }
  138. if (0 > lpPS->cLinkTypes || lpPS->cLinkTypes > PS_MAXLINKTYPES ||
  139. IsBadReadPtr(lpPS->arrLinkTypes, lpPS->cLinkTypes * sizeof(UINT)))
  140. {
  141. uRet = OLEUI_IOERR_ARRLINKTYPESINVALID;
  142. }
  143. if (0 != lpPS->cClsidExclude &&
  144. IsBadReadPtr(lpPS->lpClsidExclude, lpPS->cClsidExclude * sizeof(CLSID)))
  145. {
  146. uRet = OLEUI_IOERR_LPCLSIDEXCLUDEINVALID;
  147. }
  148. // If IDataObject passed is NULL, collect it from the clipboard
  149. if (NULL == lpPS->lpSrcDataObj)
  150. {
  151. if (OleGetClipboard(&lpPS->lpSrcDataObj) != NOERROR)
  152. uRet = OLEUI_PSERR_GETCLIPBOARDFAILED;
  153. if (NULL == lpPS->lpSrcDataObj)
  154. uRet = OLEUI_PSERR_GETCLIPBOARDFAILED;
  155. }
  156. if (uRet >= OLEUI_ERR_STANDARDMIN)
  157. {
  158. return uRet;
  159. }
  160. UINT nIDD = bWin4 ? IDD_PASTESPECIAL4 : IDD_PASTESPECIAL;
  161. //Now that we've validated everything, we can invoke the dialog.
  162. uRet = UStandardInvocation(PasteSpecialDialogProc, (LPOLEUISTANDARD)lpPS,
  163. hMemDlg, MAKEINTRESOURCE(nIDD));
  164. return uRet;
  165. }
  166. /*
  167. * PasteSpecialDialogProc
  168. *
  169. * Purpose:
  170. * Implements the OLE Paste Special dialog as invoked through the
  171. * OleUIPasteSpecial function.
  172. *
  173. * Parameters:
  174. * Standard
  175. *
  176. * Return Value:
  177. * Standard
  178. */
  179. INT_PTR CALLBACK PasteSpecialDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
  180. {
  181. // Declare Win16/Win32 compatible WM_COMMAND parameters.
  182. COMMANDPARAMS(wID, wCode, hWndMsg);
  183. // This will fail under WM_INITDIALOG, where we allocate it.
  184. UINT fHook = FALSE;
  185. LPPASTESPECIAL lpPS = (LPPASTESPECIAL)LpvStandardEntry(
  186. hDlg, iMsg, wParam, lParam, &fHook);
  187. LPOLEUIPASTESPECIAL lpOPS = NULL;
  188. if (lpPS != NULL)
  189. lpOPS = lpPS->lpOPS;
  190. //If the hook processed the message, we're done.
  191. if (0!=fHook)
  192. return (INT_PTR)fHook;
  193. // Process help message from Change Icon
  194. if (iMsg == uMsgHelp)
  195. {
  196. // if lPS is NULL (in low memory situations, just ignore it.
  197. if (lpPS && (lpPS->lpOPS) )
  198. {
  199. PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp, wParam, lParam);
  200. }
  201. return FALSE;
  202. }
  203. //Process the temination message
  204. if (iMsg == uMsgEndDialog)
  205. {
  206. EndDialog(hDlg, wParam);
  207. return TRUE;
  208. }
  209. switch (iMsg)
  210. {
  211. case WM_DESTROY:
  212. if (lpPS)
  213. {
  214. HWND hwndNextViewer;
  215. // Free the icon/icon-title metafile corresponding to Paste/PasteList option which is not selected
  216. if (lpPS->fLink)
  217. OleUIMetafilePictIconFree(lpPS->hMetaPictOD);
  218. else
  219. OleUIMetafilePictIconFree(lpPS->hMetaPictLSD);
  220. // Free data associated with each list box entry
  221. FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELIST));
  222. FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELINKLIST));
  223. //Free any specific allocations before calling StandardCleanup
  224. if (lpPS->hObjDesc) GlobalFree(lpPS->hObjDesc);
  225. if (lpPS->hLinkSrcDesc) GlobalFree(lpPS->hLinkSrcDesc);
  226. if (lpPS->hBuff)
  227. {
  228. GlobalFree(lpPS->hBuff);
  229. lpPS->hBuff = NULL;
  230. }
  231. // Change the clipboard notification chain
  232. hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER);
  233. if (hwndNextViewer != HWND_BROADCAST)
  234. {
  235. SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
  236. ChangeClipboardChain(hDlg, hwndNextViewer);
  237. }
  238. RemoveProp(hDlg, NEXTCBVIEWER);
  239. StandardCleanup(lpPS, hDlg);
  240. }
  241. break;
  242. case WM_INITDIALOG:
  243. FPasteSpecialInit(hDlg, wParam, lParam);
  244. return FALSE;
  245. case WM_DRAWCLIPBOARD:
  246. {
  247. HWND hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER);
  248. HWND hDlg_ChgIcon;
  249. if (hwndNextViewer == HWND_BROADCAST)
  250. break;
  251. if (hwndNextViewer)
  252. {
  253. SendMessage(hwndNextViewer, iMsg, wParam, lParam);
  254. // Refresh next viewer in case it got modified
  255. // by the SendMessage() (likely if multiple
  256. // PasteSpecial dialogs are up simultaneously)
  257. hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER);
  258. }
  259. if (!(lpPS->dwFlags & PSF_STAYONCLIPBOARDCHANGE))
  260. {
  261. SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
  262. ChangeClipboardChain(hDlg, hwndNextViewer);
  263. /* OLE2NOTE: if the ChangeIcon dialog is currently up, then
  264. ** we need to defer bringing down PasteSpecial dialog
  265. ** until after ChangeIcon dialog returns. if the
  266. ** ChangeIcon dialog is NOT up, then we can bring down
  267. ** the PasteSpecial dialog immediately.
  268. */
  269. if ((hDlg_ChgIcon=(HWND)GetProp(hDlg,PROP_HWND_CHGICONDLG))!=NULL)
  270. {
  271. // ChangeIcon dialog is UP
  272. lpPS->fClipboardChanged = TRUE;
  273. }
  274. else
  275. {
  276. // ChangeIcon dialog is NOT up
  277. // Free icon and icon title metafile
  278. SendDlgItemMessage(
  279. hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L);
  280. SendMessage(
  281. hDlg, uMsgEndDialog, OLEUI_PSERR_CLIPBOARDCHANGED,0L);
  282. }
  283. }
  284. else
  285. {
  286. // skip refresh, ignoring clipboard change if PSF_NOREFRESHDATAOBJECT
  287. if (lpPS->dwFlags & PSF_NOREFRESHDATAOBJECT)
  288. break;
  289. // release current data object
  290. if (lpOPS->lpSrcDataObj != NULL)
  291. {
  292. lpOPS->lpSrcDataObj->Release();
  293. lpOPS->lpSrcDataObj = NULL;
  294. }
  295. // obtain new one
  296. if (OleGetClipboard(&lpOPS->lpSrcDataObj) != NOERROR)
  297. {
  298. SendMessage(hDlg, uMsgEndDialog, OLEUI_PSERR_GETCLIPBOARDFAILED, 0);
  299. break;
  300. }
  301. // otherwise update the display to the new clipboard object
  302. FPasteSpecialReInit(hDlg, lpPS);
  303. }
  304. }
  305. break;
  306. case WM_CHANGECBCHAIN:
  307. {
  308. HWND hwndNextViewer = (HWND)GetProp(hDlg, NEXTCBVIEWER);
  309. if ((HWND)wParam == hwndNextViewer)
  310. SetProp(hDlg, NEXTCBVIEWER, (hwndNextViewer = (HWND)lParam));
  311. else if (hwndNextViewer && hwndNextViewer != HWND_BROADCAST)
  312. SendMessage(hwndNextViewer, iMsg, wParam, lParam);
  313. }
  314. break;
  315. case WM_COMMAND:
  316. switch (wID)
  317. {
  318. case IDC_PS_PASTE:
  319. FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE);
  320. break;
  321. case IDC_PS_PASTELINK:
  322. FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK);
  323. break;
  324. case IDC_PS_DISPLAYLIST:
  325. switch (wCode)
  326. {
  327. case LBN_SELCHANGE:
  328. ChangeListSelection(hDlg, lpPS, hWndMsg);
  329. break;
  330. case LBN_DBLCLK:
  331. // Same as pressing OK
  332. if (IsWindowEnabled(GetDlgItem(hDlg, IDOK)))
  333. SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
  334. break;
  335. }
  336. break;
  337. case IDC_PS_DISPLAYASICON:
  338. ToggleDisplayAsIcon(hDlg, lpPS);
  339. break;
  340. case IDC_PS_CHANGEICON:
  341. ChangeIcon(hDlg, lpPS);
  342. if (lpPS->fClipboardChanged)
  343. {
  344. // Free icon and icon title metafile
  345. SendDlgItemMessage(
  346. hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEFREE,0,0L);
  347. SendMessage(hDlg, uMsgEndDialog,
  348. OLEUI_PSERR_CLIPBOARDCHANGED, 0L);
  349. }
  350. break;
  351. case IDOK:
  352. {
  353. BOOL fDestAspectIcon =
  354. ((lpPS->dwFlags & PSF_CHECKDISPLAYASICON) ?
  355. TRUE : FALSE);
  356. // Return current flags
  357. lpOPS->dwFlags = lpPS->dwFlags;
  358. // Return index of arrPasteEntries[] corresponding to format selected by user
  359. lpOPS->nSelectedIndex = lpPS->nSelectedIndex;
  360. // Return if user selected Paste or PasteLink
  361. lpOPS->fLink = lpPS->fLink;
  362. /* if user selected same ASPECT as displayed in the
  363. ** source, then sizel passed in the
  364. ** ObjectDescriptor/LinkSrcDescriptor is
  365. ** applicable. otherwise, the sizel does not apply.
  366. */
  367. if (lpPS->fLink)
  368. {
  369. if (lpPS->fSrcAspectIconLSD == fDestAspectIcon)
  370. lpOPS->sizel = lpPS->sizelLSD;
  371. else
  372. lpOPS->sizel.cx = lpOPS->sizel.cy = 0;
  373. }
  374. else
  375. {
  376. if (lpPS->fSrcAspectIconOD == fDestAspectIcon)
  377. lpOPS->sizel = lpPS->sizelOD;
  378. else
  379. lpOPS->sizel.cx = lpOPS->sizel.cy = 0;
  380. }
  381. // Return metafile with icon and icon title that the user selected
  382. lpOPS->hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg,
  383. IDC_PS_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
  384. SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
  385. }
  386. break;
  387. case IDCANCEL:
  388. // Free icon and icon title metafile
  389. SendDlgItemMessage(
  390. hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L);
  391. SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
  392. break;
  393. case IDC_OLEUIHELP:
  394. PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp,
  395. (WPARAM)hDlg, MAKELPARAM(IDD_PASTESPECIAL, 0));
  396. break;
  397. }
  398. break;
  399. }
  400. return FALSE;
  401. }
  402. BOOL FPasteSpecialReInit(HWND hDlg, LPPASTESPECIAL lpPS)
  403. {
  404. LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
  405. // free the icon/icon-title metafiel
  406. if (lpPS->fLink)
  407. OleUIMetafilePictIconFree(lpPS->hMetaPictOD);
  408. else
  409. OleUIMetafilePictIconFree(lpPS->hMetaPictLSD);
  410. // Free data assocatiated with each list box entry
  411. FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELIST));
  412. FreeListData(GetDlgItem(hDlg, IDC_PS_PASTELINKLIST));
  413. SendDlgItemMessage(hDlg, IDC_PS_DISPLAYLIST, LB_RESETCONTENT, 0, 0);
  414. // Initialize user selections in the Paste and PasteLink listboxes
  415. lpPS->nPasteListCurSel = 0;
  416. lpPS->nPasteLinkListCurSel = 0;
  417. // Free previous object descriptor/link descriptor data
  418. if (lpPS->hObjDesc != NULL)
  419. {
  420. GlobalFree(lpPS->hObjDesc);
  421. lpPS->hObjDesc = NULL;
  422. }
  423. if (lpPS->hLinkSrcDesc != NULL)
  424. {
  425. GlobalFree(lpPS->hLinkSrcDesc);
  426. lpPS->hLinkSrcDesc = NULL;
  427. }
  428. lpPS->szAppName[0] = '\0';
  429. // GetData CF_OBJECTDESCRIPTOR. If the object on the clipboard in an
  430. // OLE1 object (offering CF_OWNERLINK) or has been copied to
  431. // clipboard by FileMaager (offering CF_FILENAME), an
  432. // OBJECTDESCRIPTOR will be created will be created from CF_OWNERLINK
  433. // or CF_FILENAME. See OBJECTDESCRIPTOR for more info.
  434. STGMEDIUM medium;
  435. CLIPFORMAT cfFormat;
  436. lpPS->hObjDesc = OleStdFillObjectDescriptorFromData(
  437. lpOPS->lpSrcDataObj, &medium, &cfFormat);
  438. if (lpPS->hObjDesc)
  439. {
  440. LPOBJECTDESCRIPTOR lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(lpPS->hObjDesc);
  441. // Get FullUserTypeName, SourceOfCopy and CLSID
  442. if (lpOD->dwFullUserTypeName)
  443. lstrcpyn(lpPS->szFullUserTypeNameOD, (LPTSTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), PS_UNKNOWNNAMELEN);
  444. else
  445. lstrcpyn(lpPS->szFullUserTypeNameOD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN);
  446. if (lpOD->dwSrcOfCopy)
  447. {
  448. lstrcpyn(lpPS->szSourceOfDataOD, (LPTSTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), PS_UNKNOWNNAMELEN);
  449. // If CF_FILENAME was offered, source of copy is a
  450. // path name. Fit the path to the static control that will display it.
  451. if (cfFormat == _g_cfFileName)
  452. {
  453. lstrcpyn(lpPS->szSourceOfDataOD, ChopText(GetDlgItem(hDlg, IDC_PS_SOURCETEXT), 0,
  454. lpPS->szSourceOfDataOD, 0), PS_UNKNOWNNAMELEN);
  455. }
  456. }
  457. else
  458. lstrcpyn(lpPS->szSourceOfDataOD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN);
  459. lpPS->clsidOD = lpOD->clsid;
  460. lpPS->sizelOD = lpOD->sizel;
  461. // Does source specify DVASPECT_ICON?
  462. if (lpOD->dwDrawAspect & DVASPECT_ICON)
  463. lpPS->fSrcAspectIconOD = TRUE;
  464. else
  465. lpPS->fSrcAspectIconOD = FALSE;
  466. // Does source specify OLEMISC_ONLYICONIC?
  467. if (lpOD->dwStatus & OLEMISC_ONLYICONIC)
  468. lpPS->fSrcOnlyIconicOD = TRUE;
  469. else
  470. lpPS->fSrcOnlyIconicOD = FALSE;
  471. // Get application name of source from auxusertype3 in the registration database
  472. LPOLESTR lpszAppName = NULL;
  473. if (OleRegGetUserType(lpPS->clsidOD, USERCLASSTYPE_APPNAME,
  474. &lpszAppName) == NOERROR)
  475. {
  476. lstrcpyn(lpPS->szAppName, lpszAppName, OLEUI_CCHKEYMAX);
  477. OleStdFree(lpszAppName);
  478. }
  479. else
  480. {
  481. if (0 == LoadString(_g_hOleStdResInst, IDS_PSUNKNOWNAPP, lpPS->szAppName,
  482. PS_UNKNOWNSTRLEN))
  483. {
  484. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
  485. return FALSE;
  486. }
  487. }
  488. // Retrieve an icon from the object
  489. if (lpPS->fSrcAspectIconOD)
  490. {
  491. lpPS->hMetaPictOD = OleStdGetData(
  492. lpOPS->lpSrcDataObj,
  493. (CLIPFORMAT) CF_METAFILEPICT,
  494. NULL,
  495. DVASPECT_ICON,
  496. &medium
  497. );
  498. }
  499. // If object does not offer icon, obtain it from the CLSID
  500. if (NULL == lpPS->hMetaPictOD)
  501. lpPS->hMetaPictOD = OleGetIconOfClass(lpPS->clsidOD, NULL, TRUE);
  502. }
  503. // Does object offer CF_LINKSRCDESCRIPTOR?
  504. lpPS->hLinkSrcDesc = OleStdGetData(
  505. lpOPS->lpSrcDataObj,
  506. (CLIPFORMAT) _g_cfLinkSrcDescriptor,
  507. NULL,
  508. DVASPECT_CONTENT,
  509. &medium);
  510. if (lpPS->hLinkSrcDesc)
  511. {
  512. // Get FullUserTypeName, SourceOfCopy and CLSID
  513. LPLINKSRCDESCRIPTOR lpLSD = (LPLINKSRCDESCRIPTOR)GlobalLock(lpPS->hLinkSrcDesc);
  514. if (lpLSD->dwFullUserTypeName)
  515. lstrcpyn(lpPS->szFullUserTypeNameLSD, (LPTSTR)((LPBYTE)lpLSD+lpLSD->dwFullUserTypeName), PS_UNKNOWNNAMELEN);
  516. else
  517. lstrcpyn(lpPS->szFullUserTypeNameLSD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN);
  518. if (lpLSD->dwSrcOfCopy)
  519. lstrcpyn(lpPS->szSourceOfDataLSD, (LPTSTR)((LPBYTE)lpLSD+lpLSD->dwSrcOfCopy), PS_UNKNOWNNAMELEN);
  520. else
  521. lstrcpyn(lpPS->szSourceOfDataLSD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN);
  522. // if no ObjectDescriptor, then use LinkSourceDescriptor source string
  523. if (!lpPS->hObjDesc)
  524. lstrcpyn(lpPS->szSourceOfDataOD, lpPS->szSourceOfDataLSD, PS_UNKNOWNNAMELEN);
  525. lpPS->clsidLSD = lpLSD->clsid;
  526. lpPS->sizelLSD = lpLSD->sizel;
  527. // Does source specify DVASPECT_ICON?
  528. if (lpLSD->dwDrawAspect & DVASPECT_ICON)
  529. lpPS->fSrcAspectIconLSD = TRUE;
  530. else
  531. lpPS->fSrcAspectIconLSD = FALSE;
  532. // Does source specify OLEMISC_ONLYICONIC?
  533. if (lpLSD->dwStatus & OLEMISC_ONLYICONIC)
  534. lpPS->fSrcOnlyIconicLSD = TRUE;
  535. else
  536. lpPS->fSrcOnlyIconicLSD = FALSE;
  537. // Retrieve an icon from the object
  538. if (lpPS->fSrcAspectIconLSD)
  539. {
  540. lpPS->hMetaPictLSD = OleStdGetData(
  541. lpOPS->lpSrcDataObj,
  542. CF_METAFILEPICT,
  543. NULL,
  544. DVASPECT_ICON,
  545. &medium
  546. );
  547. }
  548. // If object does not offer icon, obtain it from the CLSID
  549. if (NULL == lpPS->hMetaPictLSD)
  550. {
  551. HWND hIconWnd = GetDlgItem(hDlg, IDC_PS_ICONDISPLAY);
  552. RECT IconRect; GetClientRect(hIconWnd, &IconRect);
  553. LPTSTR lpszLabel = OleStdCopyString(lpPS->szSourceOfDataLSD);
  554. // width is 2 times width of iconbox because it can wrap
  555. int nWidth = (IconRect.right-IconRect.left) * 2;
  556. // limit text to the width or max characters
  557. LPTSTR lpszChopLabel = ChopText(hIconWnd, nWidth, lpszLabel,
  558. lstrlen(lpszLabel));
  559. lpPS->hMetaPictLSD =
  560. OleGetIconOfClass(lpPS->clsidLSD, lpszChopLabel, FALSE);
  561. OleStdFree(lpszLabel);
  562. }
  563. }
  564. else if (lpPS->hObjDesc) // Does not offer CF_LINKSRCDESCRIPTOR but offers CF_OBJECTDESCRIPTOR
  565. {
  566. // Copy the values of OBJECTDESCRIPTOR
  567. lstrcpyn(lpPS->szFullUserTypeNameLSD, lpPS->szFullUserTypeNameOD, PS_UNKNOWNNAMELEN);
  568. lstrcpyn(lpPS->szSourceOfDataLSD, lpPS->szSourceOfDataOD, PS_UNKNOWNNAMELEN);
  569. lpPS->clsidLSD = lpPS->clsidOD;
  570. lpPS->sizelLSD = lpPS->sizelOD;
  571. lpPS->fSrcAspectIconLSD = lpPS->fSrcAspectIconOD;
  572. lpPS->fSrcOnlyIconicLSD = lpPS->fSrcOnlyIconicOD;
  573. // Don't copy the hMetaPict; instead get a separate copy
  574. if (lpPS->fSrcAspectIconLSD)
  575. {
  576. lpPS->hMetaPictLSD = OleStdGetData(
  577. lpOPS->lpSrcDataObj,
  578. CF_METAFILEPICT,
  579. NULL,
  580. DVASPECT_ICON,
  581. &medium
  582. );
  583. }
  584. if (NULL == lpPS->hMetaPictLSD)
  585. {
  586. HWND hIconWnd = GetDlgItem(hDlg, IDC_PS_ICONDISPLAY);
  587. RECT IconRect; GetClientRect(hIconWnd, &IconRect);
  588. LPTSTR lpszLabel = OleStdCopyString(lpPS->szSourceOfDataLSD);
  589. // width is 2 times width of iconbox because it can wrap
  590. int nWidth = (IconRect.right-IconRect.left) * 2;
  591. // limit text to the width or max characters
  592. LPTSTR lpszChopLabel = ChopText(hIconWnd, nWidth, lpszLabel,
  593. lstrlen(lpszLabel));
  594. lpPS->hMetaPictLSD =
  595. OleGetIconOfClass(lpPS->clsidLSD, lpszChopLabel, FALSE);
  596. OleStdFree(lpszLabel);
  597. }
  598. }
  599. // Not an OLE object
  600. if (lpPS->hObjDesc == NULL && lpPS->hLinkSrcDesc == NULL)
  601. {
  602. lstrcpyn(lpPS->szFullUserTypeNameLSD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN);
  603. lstrcpyn(lpPS->szFullUserTypeNameOD, lpPS->szUnknownType, PS_UNKNOWNNAMELEN);
  604. lstrcpyn(lpPS->szSourceOfDataLSD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN);
  605. lstrcpyn(lpPS->szSourceOfDataOD, lpPS->szUnknownSource, PS_UNKNOWNNAMELEN);
  606. lpPS->hMetaPictLSD = lpPS->hMetaPictOD = NULL;
  607. }
  608. // Allocate scratch memory to construct item names in the paste and pastelink listboxes
  609. if (lpPS->hBuff != NULL)
  610. {
  611. GlobalFree(lpPS->hBuff);
  612. lpPS->hBuff = NULL;
  613. }
  614. lpPS->hBuff = AllocateScratchMem(lpPS);
  615. if (lpPS->hBuff == NULL)
  616. {
  617. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L);
  618. return FALSE;
  619. }
  620. // Select the Paste Link Button if specified. Otherwise select
  621. // Paste Button by default
  622. if (lpPS->dwFlags & PSF_SELECTPASTELINK)
  623. lpPS->dwFlags = (lpPS->dwFlags & ~PSF_SELECTPASTE) | PSF_SELECTPASTELINK;
  624. else
  625. lpPS->dwFlags =(lpPS->dwFlags & ~PSF_SELECTPASTELINK) | PSF_SELECTPASTE;
  626. // Mark which PasteEntry formats are available from source data object
  627. OleStdMarkPasteEntryList(
  628. lpOPS->lpSrcDataObj, lpOPS->arrPasteEntries, lpOPS->cPasteEntries);
  629. // Check if items are available to be pasted
  630. BOOL fPasteAvailable = FFillPasteList(hDlg, lpPS);
  631. if (!fPasteAvailable)
  632. lpPS->dwFlags &= ~PSF_SELECTPASTE;
  633. StandardEnableDlgItem(hDlg, IDC_PS_PASTE, fPasteAvailable);
  634. // Check if items are available to be paste-linked
  635. BOOL fPasteLinkAvailable = FFillPasteLinkList(hDlg, lpPS);
  636. if (!fPasteLinkAvailable)
  637. lpPS->dwFlags &= ~PSF_SELECTPASTELINK;
  638. StandardEnableDlgItem(hDlg, IDC_PS_PASTELINK, fPasteLinkAvailable);
  639. // If one of Paste or PasteLink is disabled, select the other one
  640. // regardless of what the input flags say
  641. if (fPasteAvailable && !fPasteLinkAvailable)
  642. lpPS->dwFlags |= PSF_SELECTPASTE;
  643. if (fPasteLinkAvailable && !fPasteAvailable)
  644. lpPS->dwFlags |= PSF_SELECTPASTELINK;
  645. BOOL bEnabled = TRUE;
  646. if (lpPS->dwFlags & PSF_SELECTPASTE)
  647. {
  648. // FTogglePaste will set the PSF_SELECTPASTE flag, so clear it.
  649. lpPS->dwFlags &= ~PSF_SELECTPASTE;
  650. CheckRadioButton(hDlg, IDC_PS_PASTE, IDC_PS_PASTELINK, IDC_PS_PASTE);
  651. FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE);
  652. }
  653. else if (lpPS->dwFlags & PSF_SELECTPASTELINK)
  654. {
  655. // FTogglePaste will set the PSF_SELECTPASTELINK flag, so clear it.
  656. lpPS->dwFlags &= ~PSF_SELECTPASTELINK;
  657. CheckRadioButton(hDlg, IDC_PS_PASTE, IDC_PS_PASTELINK, IDC_PS_PASTELINK);
  658. FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK);
  659. }
  660. else // Items are not available to be be Pasted or Paste-Linked
  661. {
  662. // Enable or disable DisplayAsIcon and set the result text and image
  663. EnableDisplayAsIcon(hDlg, lpPS);
  664. SetPasteSpecialHelpResults(hDlg, lpPS);
  665. SetDlgItemText(hDlg, IDC_PS_SOURCETEXT, lpPS->szSourceOfDataOD);
  666. CheckRadioButton(hDlg, IDC_PS_PASTE, IDC_PS_PASTELINK, 0);
  667. bEnabled = FALSE;
  668. }
  669. StandardEnableDlgItem(hDlg, IDOK, bEnabled);
  670. return TRUE;
  671. }
  672. /*
  673. * FPasteSpecialInit
  674. *
  675. * Purpose:
  676. * WM_INITIDIALOG handler for the Paste Special dialog box.
  677. *
  678. * Parameters:
  679. * hDlg HWND of the dialog
  680. * wParam WPARAM of the message
  681. * lParam LPARAM of the message
  682. *
  683. * Return Value:
  684. * BOOL Value to return for WM_INITDIALOG.
  685. */
  686. BOOL FPasteSpecialInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
  687. {
  688. // Copy the structure at lParam into our instance memory.
  689. HFONT hFont;
  690. LPPASTESPECIAL lpPS = (LPPASTESPECIAL)LpvStandardInit(hDlg, sizeof(PASTESPECIAL), &hFont);
  691. // PvStandardInit sent a termination to us already.
  692. if (NULL == lpPS)
  693. return FALSE;
  694. LPOLEUIPASTESPECIAL lpOPS = (LPOLEUIPASTESPECIAL)lParam;
  695. // Copy other information from lpOPS that we might modify.
  696. lpPS->lpOPS = lpOPS;
  697. lpPS->nIDD = IDD_PASTESPECIAL;
  698. lpPS->dwFlags = lpOPS->dwFlags;
  699. // If we got a font, send it to the necessary controls.
  700. if (NULL!=hFont)
  701. {
  702. SendDlgItemMessage(hDlg, IDC_PS_SOURCETEXT, WM_SETFONT, (WPARAM)hFont, 0L);
  703. SendDlgItemMessage(hDlg, IDC_PS_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L);
  704. }
  705. // Hide the help button if required
  706. if (!(lpPS->lpOPS->dwFlags & PSF_SHOWHELP))
  707. StandardShowDlgItem(hDlg, IDC_OLEUIHELP, SW_HIDE);
  708. // Show or hide the Change icon button
  709. if (lpPS->dwFlags & PSF_HIDECHANGEICON)
  710. DestroyWindow(GetDlgItem(hDlg, IDC_PS_CHANGEICON));
  711. // Hide all DisplayAsIcon related controls if it should be disabled
  712. if (lpPS->dwFlags & PSF_DISABLEDISPLAYASICON)
  713. {
  714. StandardShowDlgItem(hDlg, IDC_PS_DISPLAYASICON, SW_HIDE);
  715. StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE);
  716. StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE);
  717. }
  718. // clear PSF_CHECKDISPLAYASICON -> it's an output parameter only
  719. lpPS->dwFlags &= ~ PSF_CHECKDISPLAYASICON;
  720. // Change the caption if required
  721. if (NULL != lpOPS->lpszCaption)
  722. SetWindowText(hDlg, lpOPS->lpszCaption);
  723. // Load 'Unknown Source' and 'Unknown Type' strings
  724. int n = LoadString(_g_hOleStdResInst, IDS_PSUNKNOWNTYPE, lpPS->szUnknownType, PS_UNKNOWNSTRLEN);
  725. if (n)
  726. n = LoadString(_g_hOleStdResInst, IDS_PSUNKNOWNSRC, lpPS->szUnknownSource, PS_UNKNOWNSTRLEN);
  727. if (!n)
  728. {
  729. PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
  730. return FALSE;
  731. }
  732. if (!FPasteSpecialReInit(hDlg, lpPS))
  733. return FALSE;
  734. // Give initial focus to the list box
  735. SetFocus(GetDlgItem(hDlg, IDC_PS_DISPLAYLIST));
  736. // Set property to handle clipboard change notifications
  737. SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
  738. SetProp(hDlg, NEXTCBVIEWER, SetClipboardViewer(hDlg));
  739. lpPS->fClipboardChanged = FALSE;
  740. /*
  741. * PERFORM OTHER INITIALIZATION HERE.
  742. */
  743. // Call the hook with lCustData in lParam
  744. UStandardHook(lpPS, hDlg, WM_INITDIALOG, wParam, lpOPS->lCustData);
  745. return TRUE;
  746. }
  747. /*
  748. * FTogglePasteType
  749. *
  750. * Purpose:
  751. * Toggles between Paste and Paste Link. The Paste list and PasteLink
  752. * list are always invisible. The Display List is filled from either
  753. * the Paste list or the PasteLink list depending on which Paste radio
  754. * button is selected.
  755. *
  756. * Parameters:
  757. * hDlg HWND of the dialog
  758. * lpPS Paste Special Dialog Structure
  759. * dwOption Paste or PasteSpecial option
  760. *
  761. * Return Value:
  762. * BOOL Returns TRUE if the option has already been selected.
  763. * Otherwise the option is selected and FALSE is returned
  764. */
  765. BOOL FTogglePasteType(HWND hDlg, LPPASTESPECIAL lpPS, DWORD dwOption)
  766. {
  767. DWORD dwTemp;
  768. HWND hList, hListDisplay;
  769. LRESULT dwData;
  770. int i, nItems;
  771. LPTSTR lpsz;
  772. // Skip all this if the button is already selected
  773. if (lpPS->dwFlags & dwOption)
  774. return TRUE;
  775. dwTemp = PSF_SELECTPASTE | PSF_SELECTPASTELINK;
  776. lpPS->dwFlags = (lpPS->dwFlags & ~dwTemp) | dwOption;
  777. // Hide IconDisplay. This prevents flashing if the icon display is changed
  778. StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE);
  779. hListDisplay = GetDlgItem(hDlg, IDC_PS_DISPLAYLIST);
  780. // If Paste was selected
  781. if (lpPS->dwFlags & PSF_SELECTPASTE)
  782. {
  783. // Set the Source of the object in the clipboard
  784. SetDlgItemText(hDlg, IDC_PS_SOURCETEXT, lpPS->szSourceOfDataOD);
  785. // If an icon is available
  786. if (lpPS->hMetaPictOD)
  787. // Set the icon display
  788. SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGESET,
  789. 0, (LPARAM)lpPS->hMetaPictOD);
  790. hList = GetDlgItem(hDlg, IDC_PS_PASTELIST);
  791. // We are switching from PasteLink to Paste. Remember current selection
  792. // in PasteLink list so it can be restored.
  793. lpPS->nPasteLinkListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L);
  794. if (lpPS->nPasteLinkListCurSel == LB_ERR)
  795. lpPS->nPasteLinkListCurSel = 0;
  796. // Remember if user selected Paste or PasteLink
  797. lpPS->fLink = FALSE;
  798. }
  799. else // If PasteLink was selected
  800. {
  801. // Set the Source of the object in the clipboard
  802. SetDlgItemText(hDlg, IDC_PS_SOURCETEXT, lpPS->szSourceOfDataLSD);
  803. // If an icon is available
  804. if (lpPS->hMetaPictLSD)
  805. // Set the icon display
  806. SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY, IBXM_IMAGESET,
  807. 0, (LPARAM)lpPS->hMetaPictLSD);
  808. hList = GetDlgItem(hDlg, IDC_PS_PASTELINKLIST);
  809. // We are switching from Paste to PasteLink. Remember current selection
  810. // in Paste list so it can be restored.
  811. lpPS->nPasteListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L);
  812. if (lpPS->nPasteListCurSel == LB_ERR)
  813. lpPS->nPasteListCurSel = 0;
  814. // Remember if user selected Paste or PasteLink
  815. lpPS->fLink = TRUE;
  816. }
  817. // Turn drawing off while the Display List is being filled
  818. SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)FALSE, 0L);
  819. // Move data to Display list box
  820. SendMessage(hListDisplay, LB_RESETCONTENT, 0, 0L);
  821. nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L);
  822. lpsz = (LPTSTR)GlobalLock(lpPS->hBuff);
  823. for (i = 0; i < nItems; i++)
  824. {
  825. SendMessage(hList, LB_GETTEXT, (WPARAM)i, (LPARAM)lpsz);
  826. dwData = SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
  827. SendMessage(hListDisplay, LB_INSERTSTRING, (WPARAM)i, (LPARAM)lpsz);
  828. SendMessage(hListDisplay, LB_SETITEMDATA, (WPARAM)i, dwData);
  829. }
  830. GlobalUnlock(lpPS->hBuff);
  831. // Restore the selection in the Display List from user's last selection
  832. if (lpPS->dwFlags & PSF_SELECTPASTE)
  833. SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteListCurSel, 0L);
  834. else
  835. SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteLinkListCurSel, 0L);
  836. // Paint Display List
  837. SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)TRUE, 0L);
  838. InvalidateRect(hListDisplay, NULL, TRUE);
  839. UpdateWindow(hListDisplay);
  840. // Auto give the focus to the Display List
  841. if (GetForegroundWindow() == hDlg)
  842. SetFocus(hListDisplay);
  843. // Enable/Disable DisplayAsIcon and set the help result text and bitmap corresponding to
  844. // the current selection
  845. ChangeListSelection(hDlg, lpPS, hListDisplay);
  846. return FALSE;
  847. }
  848. /*
  849. * ChangeListSelection
  850. *
  851. * Purpose:
  852. * When the user changes the selection in the list, DisplayAsIcon is enabled or disabled,
  853. * Result text and bitmap are updated and the index of the arrPasteEntries[] corresponding
  854. * to the current format selection is saved.
  855. *
  856. * Parameters:
  857. * hDlg HWND of the dialog
  858. * lpPS Paste Special Dialog Structure
  859. * hList HWND of the List
  860. *
  861. * Return Value:
  862. * No return value
  863. */
  864. void ChangeListSelection(HWND hDlg, LPPASTESPECIAL lpPS, HWND hList)
  865. {
  866. LPPASTELISTITEMDATA lpItemData;
  867. int nCurSel;
  868. EnableDisplayAsIcon(hDlg, lpPS);
  869. SetPasteSpecialHelpResults(hDlg, lpPS);
  870. // Remember index of arrPasteEntries[] corresponding to the current selection
  871. nCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  872. if (nCurSel == LB_ERR)
  873. return;
  874. lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA,
  875. (WPARAM)nCurSel, 0L);
  876. if ((LRESULT)lpItemData == LB_ERR)
  877. return;
  878. lpPS->nSelectedIndex = lpItemData->nPasteEntriesIndex;
  879. }
  880. /*
  881. * EnableDisplayAsIcon
  882. *
  883. * Purpose:
  884. * Enable or disable the DisplayAsIcon button depending on whether
  885. * the current selection can be displayed as an icon or not. The following table describes
  886. * the state of DisplayAsIcon. The calling application is termed CONTAINER, the source
  887. * of data on the clipboard is termed SOURCE.
  888. * Y = Yes; N = No; Blank = State does not matter;
  889. * =====================================================================
  890. * SOURCE SOURCE CONTAINER DisplayAsIcon
  891. * specifies specifies specifies Initial State
  892. * DVASPECT_ICON OLEMISC_ONLYICONIC OLEUIPASTE_ENABLEICON
  893. *
  894. * N Unchecked&Disabled
  895. * Y Y Checked&Disabled
  896. * Y N Y Checked&Enabled
  897. * N N Y Unchecked&Enabled
  898. * =====================================================================
  899. *
  900. * Parameters:
  901. * hDlg HWND of the dialog
  902. * lpPS Paste Special Dialog Structure
  903. *
  904. * Return Value:
  905. * No return value
  906. */
  907. void EnableDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS)
  908. {
  909. int nIndex;
  910. BOOL fCntrEnableIcon;
  911. BOOL fSrcOnlyIconic = (lpPS->fLink) ? lpPS->fSrcOnlyIconicLSD : lpPS->fSrcOnlyIconicOD;
  912. BOOL fSrcAspectIcon = (lpPS->fLink) ? lpPS->fSrcAspectIconLSD : lpPS->fSrcAspectIconOD;
  913. HWND hList;
  914. LPPASTELISTITEMDATA lpItemData;
  915. HGLOBAL hMetaPict = (lpPS->fLink) ? lpPS->hMetaPictLSD : lpPS->hMetaPictOD;
  916. hList = GetDlgItem(hDlg, IDC_PS_DISPLAYLIST);
  917. // Get data corresponding to the current selection in the listbox
  918. nIndex = (int)SendMessage(hList, LB_GETCURSEL, 0, 0);
  919. if (nIndex != LB_ERR)
  920. {
  921. lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA, (WPARAM)nIndex, 0L);
  922. if ((LRESULT)lpItemData != LB_ERR)
  923. fCntrEnableIcon = lpItemData->fCntrEnableIcon;
  924. else fCntrEnableIcon = FALSE;
  925. }
  926. else fCntrEnableIcon = FALSE;
  927. // If there is an icon available
  928. if (hMetaPict != NULL)
  929. {
  930. if (!fCntrEnableIcon) // Does CONTAINER specify OLEUIPASTE_ENABLEICON?
  931. {
  932. // Uncheck & Disable DisplayAsIcon
  933. lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
  934. CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, FALSE);
  935. StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, FALSE);
  936. // Hide IconDisplay and ChangeIcon button
  937. StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE);
  938. StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE);
  939. }
  940. else if (fSrcOnlyIconic) // Does SOURCE specify OLEMISC_ONLYICONIC?
  941. {
  942. // Check & Disable DisplayAsIcon
  943. lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
  944. CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, TRUE);
  945. StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, FALSE);
  946. // Show IconDisplay and ChangeIcon button
  947. StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_SHOWNORMAL);
  948. StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_SHOWNORMAL);
  949. }
  950. else if (fSrcAspectIcon) // Does SOURCE specify DVASPECT_ICON?
  951. {
  952. // Check & Enable DisplayAsIcon
  953. lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
  954. CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, TRUE);
  955. StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, TRUE);
  956. // Show IconDisplay and ChangeIcon button
  957. StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_SHOWNORMAL);
  958. StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_SHOWNORMAL);
  959. }
  960. else
  961. {
  962. //Uncheck and Enable DisplayAsIcon
  963. lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
  964. CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, FALSE);
  965. StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, TRUE);
  966. // Hide IconDisplay and ChangeIcon button
  967. StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE);
  968. StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE);
  969. }
  970. }
  971. else // No icon available
  972. {
  973. // Unchecked & Disabled
  974. lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
  975. CheckDlgButton(hDlg, IDC_PS_DISPLAYASICON, FALSE);
  976. StandardEnableDlgItem(hDlg, IDC_PS_DISPLAYASICON, FALSE);
  977. // Hide IconDisplay and ChangeIcon button
  978. StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, SW_HIDE);
  979. StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, SW_HIDE);
  980. }
  981. }
  982. /*
  983. * ToggleDisplayAsIcon
  984. *
  985. * Purpose:
  986. * Toggles the DisplayAsIcon button. Hides or shows the Icon Display and
  987. * the ChangeIcon button and changes the help result text and bitmap.
  988. *
  989. * Parameters:
  990. * hDlg HWND of the dialog
  991. * lpPS Paste Special Dialog Structure
  992. *
  993. * Return Value:
  994. * None
  995. *
  996. */
  997. void ToggleDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS)
  998. {
  999. BOOL fCheck;
  1000. int i;
  1001. fCheck = IsDlgButtonChecked(hDlg, IDC_PS_DISPLAYASICON);
  1002. if (fCheck)
  1003. lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
  1004. else lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
  1005. // Set the help result text and bitmap
  1006. SetPasteSpecialHelpResults(hDlg, lpPS);
  1007. // Show or hide the Icon Display and ChangeIcon button depending
  1008. // on the check state
  1009. i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE;
  1010. StandardShowDlgItem(hDlg, IDC_PS_ICONDISPLAY, i);
  1011. StandardShowDlgItem(hDlg, IDC_PS_CHANGEICON, i);
  1012. }
  1013. /*
  1014. * ChangeIcon
  1015. *
  1016. * Purpose:
  1017. * Brings up the ChangeIcon dialog which allows the user to change
  1018. * the icon and label.
  1019. *
  1020. * Parameters:
  1021. * hDlg HWND of the dialog
  1022. * lpPS Paste Special Dialog Structure
  1023. *
  1024. * Return Value:
  1025. * None
  1026. *
  1027. */
  1028. void ChangeIcon(HWND hDlg, LPPASTESPECIAL lpPS)
  1029. {
  1030. OLEUICHANGEICON ci;
  1031. UINT uRet;
  1032. CLSID clsid = (lpPS->fLink) ? lpPS->clsidLSD : lpPS->clsidOD;
  1033. //Initialize the structure
  1034. memset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci));
  1035. ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY,
  1036. IBXM_IMAGEGET, 0, 0L);
  1037. ci.cbStruct = sizeof(ci);
  1038. ci.hWndOwner = hDlg;
  1039. ci.clsid = clsid;
  1040. ci.dwFlags = CIF_SELECTCURRENT;
  1041. // Only show help in the ChangeIcon dialog if we're showing it in this dialog.
  1042. if (lpPS->dwFlags & PSF_SHOWHELP)
  1043. ci.dwFlags |= CIF_SHOWHELP;
  1044. // Let the hook in to customize Change Icon if desired.
  1045. uRet = UStandardHook(lpPS, hDlg, uMsgChangeIcon, 0, (LPARAM)&ci);
  1046. if (0 == uRet)
  1047. uRet=(UINT)(OLEUI_OK==OleUIChangeIcon(&ci));
  1048. // Update the display if necessary.
  1049. if (0!=uRet)
  1050. {
  1051. /*
  1052. * OleUIChangeIcon will have already freed our
  1053. * current hMetaPict that we passed in when OK is
  1054. * pressed in that dialog. So we use 0L as lParam
  1055. * here so the IconBox doesn't try to free the
  1056. * metafilepict again.
  1057. */
  1058. SendDlgItemMessage(hDlg, IDC_PS_ICONDISPLAY,
  1059. IBXM_IMAGESET, 0, (LPARAM)ci.hMetaPict);
  1060. // Remember the new icon chosen by the user. Note that Paste and PasteLink have separate
  1061. // icons - changing one does not change the other.
  1062. if (lpPS->fLink)
  1063. lpPS->hMetaPictLSD = ci.hMetaPict;
  1064. else
  1065. lpPS->hMetaPictOD = ci.hMetaPict;
  1066. }
  1067. }
  1068. /*
  1069. *SetPasteSpecialHelpResults
  1070. *
  1071. * Purpose:
  1072. * Sets the help result text and bitmap according to the current
  1073. * list selection. The following state table indicates which ResultText
  1074. * and ResultImage are selected. If %s in the lpstrFormatName is present,
  1075. * it is assumed that an object is being pasted/paste-linked, otherwise it
  1076. * is assumed that data is being pasted/paste-linked.
  1077. * Y = Yes; N = No; Blank = State does not matter;
  1078. * The numbers in the the ResultText and ResultImage columns refer to the table
  1079. * entries that follow.
  1080. * =====================================================================
  1081. * Paste/ lpstrFormatName in DisplayAsIcon Result Result
  1082. * PasteLink arrPasteEntry[]contains %s checked Text Image
  1083. * (Is Object == Y, Is Data == N)
  1084. * Paste N 1 1
  1085. * Paste Y N 2 2
  1086. * Paste Y Y 3 3
  1087. * PasteLink N 4 4
  1088. * PasteLink Y N 5 4
  1089. * PasteLink Y Y 6 5
  1090. * =====================================================================
  1091. * Result Text:
  1092. *
  1093. * 1. "Inserts the contents of the Clipboard into your document as <native type name,
  1094. * and optionally an additional help sentence>"
  1095. * 2. "Inserts the contents of the Clipboard into your document so that you may
  1096. * activate it using <object app name>"
  1097. * 3. "Inserts the contents of the Clipboard into your document so that you may
  1098. * activate it using <object app name>. It will be displayed as an icon."
  1099. * 4. "Inserts the contents of the Clipboard into your document as <native type name>.
  1100. * Paste Link creates a link to the source file so that changes to the source file
  1101. * will be reflected in your document."
  1102. * 5. "Inserts a picture of the Clipboard contents into your document. Paste Link
  1103. * creates a link to the source file so that changes to the source file will be
  1104. * reflected in your document."
  1105. * 6. "Inserts an icon into your document which represents the Clipboard contents.
  1106. * Paste Link creates a link to the source file so that changes to the source file
  1107. * will be reflected in your document."
  1108. * =====================================================================
  1109. * Result Image:
  1110. *
  1111. * 1. Clipboard Image
  1112. * 2. Paste image, non-iconic.
  1113. * 3. Paste image, iconic.
  1114. * 4. Paste Link image, non-iconic
  1115. * 5. Paste Link image, iconic
  1116. * ====================================================================
  1117. *
  1118. * Parameters:
  1119. * hDlg HWND of the dialog
  1120. * lpPS Paste Special Dialog Structure
  1121. *
  1122. * Return Value:
  1123. * No return value
  1124. */
  1125. void SetPasteSpecialHelpResults(HWND hDlg, LPPASTESPECIAL lpPS)
  1126. {
  1127. LPTSTR psz1, psz2, psz3, psz4;
  1128. UINT i, iString, iImage, cch;
  1129. int nPasteEntriesIndex;
  1130. BOOL fDisplayAsIcon;
  1131. BOOL fIsObject;
  1132. HWND hList;
  1133. LPPASTELISTITEMDATA lpItemData;
  1134. LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
  1135. LPTSTR szFullUserTypeName = (lpPS->fLink) ?
  1136. lpPS->szFullUserTypeNameLSD : lpPS->szFullUserTypeNameOD;
  1137. LPTSTR szInsert;
  1138. hList = GetDlgItem(hDlg, IDC_PS_DISPLAYLIST);
  1139. i=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
  1140. if (i != LB_ERR)
  1141. {
  1142. lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, i, 0L);
  1143. if ((LRESULT)lpItemData == LB_ERR) return;
  1144. nPasteEntriesIndex = lpItemData->nPasteEntriesIndex;
  1145. // Check if there is a '%s' in the lpstrFormatName, then an object is being
  1146. // pasted/pastelinked. Otherwise Data is being pasted-pastelinked.
  1147. fIsObject = FHasPercentS(lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName,
  1148. lpPS);
  1149. }
  1150. else
  1151. return;
  1152. // Is DisplayAsIcon checked?
  1153. fDisplayAsIcon=(0L!=(lpPS->dwFlags & PSF_CHECKDISPLAYASICON));
  1154. szInsert = szFullUserTypeName;
  1155. if (lpPS->dwFlags & PSF_SELECTPASTE) // If user selected Paste
  1156. {
  1157. if (fIsObject)
  1158. {
  1159. iString = fDisplayAsIcon ? IDS_PSPASTEOBJECTASICON : IDS_PSPASTEOBJECT;
  1160. iImage = fDisplayAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
  1161. szInsert = lpPS->szAppName;
  1162. }
  1163. else
  1164. {
  1165. iString = IDS_PSPASTEDATA;
  1166. iImage = RESULTIMAGE_PASTE;
  1167. }
  1168. }
  1169. else if (lpPS->dwFlags & PSF_SELECTPASTELINK) // User selected PasteLink
  1170. {
  1171. if (fIsObject)
  1172. {
  1173. iString = fDisplayAsIcon ? IDS_PSPASTELINKOBJECTASICON : IDS_PSPASTELINKOBJECT;
  1174. iImage = fDisplayAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK;
  1175. }
  1176. else
  1177. {
  1178. iString = IDS_PSPASTELINKDATA;
  1179. iImage = RESULTIMAGE_LINK;
  1180. }
  1181. }
  1182. else // Should never occur.
  1183. {
  1184. iString = IDS_PSNONOLE;
  1185. iImage = RESULTIMAGE_PASTE;
  1186. }
  1187. // hBuff contains enough space for the 4 buffers required to build up the help
  1188. // result text.
  1189. cch = (UINT)(GlobalSize(lpPS->hBuff) / sizeof(TCHAR)) / 4;
  1190. psz1 = (LPTSTR)GlobalLock(lpPS->hBuff);
  1191. psz2 = psz1 + cch;
  1192. psz3 = psz2 + cch;
  1193. psz4 = psz3 + cch;
  1194. // Default is an empty string.
  1195. *psz1 = 0;
  1196. if (0 != LoadString(_g_hOleStdResInst, iString, psz1, cch) &&
  1197. nPasteEntriesIndex != -1)
  1198. {
  1199. // Insert the FullUserTypeName of the source object into the partial result text
  1200. // specified by the container.
  1201. StringCchPrintf(psz3, cch, lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrResultText,
  1202. (LPTSTR)szInsert);
  1203. // Insert the above partial result text into the standard result text.
  1204. StringCchPrintf(psz4, cch, psz1, (LPTSTR)psz3);
  1205. psz1 = psz4;
  1206. }
  1207. // If LoadString failed, we simply clear out the results (*psz1 = 0 above)
  1208. SetDlgItemText(hDlg, IDC_PS_RESULTTEXT, psz1);
  1209. GlobalUnlock(lpPS->hBuff);
  1210. // Change the result bitmap
  1211. SendDlgItemMessage(hDlg, IDC_PS_RESULTIMAGE, RIM_IMAGESET, iImage, 0L);
  1212. }
  1213. /*
  1214. * FAddPasteListItem
  1215. *
  1216. * Purpose:
  1217. * Adds an item to the list box
  1218. *
  1219. * Parameters:
  1220. * hList HWND List into which item is to be added
  1221. * fInsertFirst BOOL Insert in the beginning of the list?
  1222. * nPasteEntriesIndex int Index of Paste Entry array this list item corresponsds to
  1223. * lpPS Paste Special Dialog Structure
  1224. * lpszBuf LPSTR Scratch buffer to build up string for list entry
  1225. * lpszFullUserTypeName LPSTR full user type name for object entry
  1226. *
  1227. * Return Value:
  1228. * BOOL TRUE if sucessful.
  1229. * FALSE if unsucessful.
  1230. */
  1231. BOOL FAddPasteListItem(
  1232. HWND hList, BOOL fInsertFirst, int nPasteEntriesIndex,
  1233. LPPASTESPECIAL lpPS, LPTSTR lpszBuf, UINT cchBuf, LPTSTR lpszFullUserTypeName)
  1234. {
  1235. LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
  1236. LPPASTELISTITEMDATA lpItemData;
  1237. int nIndex;
  1238. // Allocate memory for each list box item
  1239. lpItemData = (LPPASTELISTITEMDATA)OleStdMalloc(sizeof(PASTELISTITEMDATA));
  1240. if (NULL == lpItemData)
  1241. return FALSE;
  1242. // Fill data associated with each list box item
  1243. lpItemData->nPasteEntriesIndex = nPasteEntriesIndex;
  1244. lpItemData->fCntrEnableIcon = ((lpOPS->arrPasteEntries[nPasteEntriesIndex].dwFlags &
  1245. OLEUIPASTE_ENABLEICON) ? TRUE : FALSE);
  1246. // Build list box entry string, insert the string and add the data the corresponds to it
  1247. StringCchPrintf(
  1248. lpszBuf, cchBuf,
  1249. lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName,
  1250. lpszFullUserTypeName
  1251. );
  1252. // only add to listbox if not a duplicate
  1253. if (LB_ERR!=SendMessage(hList,LB_FINDSTRING, 0, (LPARAM)lpszBuf))
  1254. {
  1255. // item is already in list; SKIP this one
  1256. OleStdFree((LPVOID)lpItemData);
  1257. return TRUE; // this is NOT an error
  1258. }
  1259. nIndex = (int)SendMessage(
  1260. hList,
  1261. (fInsertFirst ? LB_INSERTSTRING : LB_ADDSTRING),
  1262. 0,
  1263. (LPARAM)lpszBuf
  1264. );
  1265. SendMessage(
  1266. hList,
  1267. LB_SETITEMDATA,
  1268. nIndex,
  1269. (LPARAM)(LPPASTELISTITEMDATA)lpItemData
  1270. );
  1271. return TRUE;
  1272. }
  1273. /*
  1274. * FFillPasteList
  1275. *
  1276. * Purpose:
  1277. * Fills the invisible paste list with the formats offered by the clipboard object and
  1278. * asked for by the container.
  1279. *
  1280. * Parameters:
  1281. * hDlg HWND of the dialog
  1282. * lpPS Paste Special Dialog Structure
  1283. *
  1284. * Return Value:
  1285. * BOOL TRUE if sucessful and if formats could be found.
  1286. * FALSE if unsucessful or if no formats could be found.
  1287. */
  1288. BOOL FFillPasteList(HWND hDlg, LPPASTESPECIAL lpPS)
  1289. {
  1290. LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
  1291. HWND hList;
  1292. int i, j;
  1293. int nItems = 0;
  1294. int nDefFormat = -1;
  1295. BOOL fTryObjFmt = FALSE;
  1296. BOOL fInsertFirst;
  1297. BOOL fExclude;
  1298. hList = GetDlgItem(hDlg, IDC_PS_PASTELIST);
  1299. SendMessage(hList, LB_RESETCONTENT, 0, 0);
  1300. // Loop over the target's priority list of formats
  1301. for (i = 0; i < lpOPS->cPasteEntries; i++)
  1302. {
  1303. if (lpOPS->arrPasteEntries[i].dwFlags != OLEUIPASTE_PASTEONLY &&
  1304. !(lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_PASTE))
  1305. continue;
  1306. fInsertFirst = FALSE;
  1307. if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfFileName
  1308. || lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfEmbeddedObject
  1309. || lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfEmbedSource)
  1310. {
  1311. if (! fTryObjFmt)
  1312. {
  1313. fTryObjFmt = TRUE; // only use 1st object format
  1314. fInsertFirst = TRUE; // OLE obj format should always be 1st
  1315. //Check if this CLSID is in the exclusion list.
  1316. fExclude=FALSE;
  1317. for (j=0; j < (int)lpOPS->cClsidExclude; j++)
  1318. {
  1319. if (IsEqualCLSID(lpPS->clsidOD, lpOPS->lpClsidExclude[j]))
  1320. {
  1321. fExclude=TRUE;
  1322. break;
  1323. }
  1324. }
  1325. if (fExclude)
  1326. continue; // don't add the object entry to list
  1327. }
  1328. else
  1329. {
  1330. continue; // already added an object format to list
  1331. }
  1332. }
  1333. // add to list if entry is marked TRUE
  1334. if (lpOPS->arrPasteEntries[i].dwScratchSpace)
  1335. {
  1336. if (nDefFormat < 0)
  1337. nDefFormat = (fInsertFirst ? 0 : nItems);
  1338. else if (fInsertFirst)
  1339. nDefFormat++; // adjust for obj fmt inserted 1st in list
  1340. LPTSTR lpszBuf = (LPTSTR)GlobalLock(lpPS->hBuff);
  1341. if (lpszBuf)
  1342. {
  1343. UINT cchMax = (UINT)GlobalSize(lpPS->hBuff) / sizeof (TCHAR);
  1344. if (!FAddPasteListItem(hList, fInsertFirst, i, lpPS,
  1345. lpszBuf, cchMax, lpPS->szFullUserTypeNameOD))
  1346. {
  1347. GlobalUnlock(lpPS->hBuff);
  1348. goto error;
  1349. }
  1350. GlobalUnlock(lpPS->hBuff);
  1351. }
  1352. nItems++;
  1353. }
  1354. }
  1355. // initialize selection to first format matched in list
  1356. if (nDefFormat >= 0)
  1357. lpPS->nPasteListCurSel = nDefFormat;
  1358. // Clean up
  1359. // If no items have been added to the list box (none of the formats
  1360. // offered by the source matched those acceptable to the container),
  1361. // return FALSE
  1362. if (nItems > 0)
  1363. return TRUE;
  1364. else
  1365. return FALSE;
  1366. error:
  1367. FreeListData(hList);
  1368. return FALSE;
  1369. }
  1370. /*
  1371. * FFillPasteLinkList
  1372. *
  1373. * Purpose:
  1374. * Fills the invisible paste link list with the formats offered by the clipboard object and
  1375. * asked for by the container.
  1376. *
  1377. * Parameters:
  1378. * hDlg HWND of the dialog
  1379. * lpPS Paste Special Dialog Structure
  1380. *
  1381. * Return Value:
  1382. * BOOL TRUE if sucessful and if formats could be found.
  1383. * FALSE if unsucessful or if no formats could be found.
  1384. */
  1385. BOOL FFillPasteLinkList(HWND hDlg, LPPASTESPECIAL lpPS)
  1386. {
  1387. LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
  1388. LPDATAOBJECT lpSrcDataObj = lpOPS->lpSrcDataObj;
  1389. LPENUMFORMATETC lpEnumFmtEtc = NULL;
  1390. OLEUIPASTEFLAG pasteFlag;
  1391. UINT arrLinkTypesSupported[PS_MAXLINKTYPES]; // Array of flags that
  1392. // indicate which link types
  1393. // are supported by source.
  1394. FORMATETC fmtetc;
  1395. int i, j;
  1396. int nItems = 0;
  1397. BOOL fLinkTypeSupported = FALSE;
  1398. HWND hList;
  1399. int nDefFormat = -1;
  1400. BOOL fTryObjFmt = FALSE;
  1401. BOOL fInsertFirst;
  1402. HRESULT hrErr;
  1403. // Remember which link type formats are offered by lpSrcDataObj.
  1404. memset(&fmtetc, 0, sizeof(FORMATETC));
  1405. for (i = 0; i < lpOPS->cLinkTypes; i++)
  1406. {
  1407. if (lpOPS->arrLinkTypes[i] == _g_cfLinkSource)
  1408. {
  1409. OLEDBG_BEGIN2(TEXT("OleQueryLinkFromData called\r\n"))
  1410. hrErr = OleQueryLinkFromData(lpSrcDataObj);
  1411. OLEDBG_END2
  1412. if(NOERROR == hrErr)
  1413. {
  1414. arrLinkTypesSupported[i] = 1;
  1415. fLinkTypeSupported = TRUE;
  1416. }
  1417. else
  1418. arrLinkTypesSupported[i] = 0;
  1419. }
  1420. else
  1421. {
  1422. fmtetc.cfFormat = (CLIPFORMAT)lpOPS->arrLinkTypes[i];
  1423. fmtetc.dwAspect = DVASPECT_CONTENT;
  1424. fmtetc.tymed = 0xFFFFFFFF; // All tymed values
  1425. fmtetc.lindex = -1;
  1426. OLEDBG_BEGIN2(TEXT("IDataObject::QueryGetData called\r\n"))
  1427. hrErr = lpSrcDataObj->QueryGetData(&fmtetc);
  1428. OLEDBG_END2
  1429. if(NOERROR == hrErr)
  1430. {
  1431. arrLinkTypesSupported[i] = 1;
  1432. fLinkTypeSupported = TRUE;
  1433. }
  1434. else arrLinkTypesSupported[i] = 0;
  1435. }
  1436. }
  1437. // No link types are offered by lpSrcDataObj
  1438. if (! fLinkTypeSupported)
  1439. {
  1440. nItems = 0;
  1441. goto cleanup;
  1442. }
  1443. hList = GetDlgItem(hDlg, IDC_PS_PASTELINKLIST);
  1444. SendMessage(hList, LB_RESETCONTENT, 0, 0);
  1445. // Enumerate the formats acceptable to container
  1446. for (i = 0; i < lpOPS->cPasteEntries; i++)
  1447. {
  1448. fLinkTypeSupported = FALSE;
  1449. // If container will accept any link type offered by source object
  1450. if (lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_LINKANYTYPE)
  1451. fLinkTypeSupported = TRUE;
  1452. else
  1453. {
  1454. // Check if any of the link types offered by the source
  1455. // object are acceptable to the container
  1456. // This code depends on the LINKTYPE enum values being powers of 2
  1457. for (pasteFlag = OLEUIPASTE_LINKTYPE1, j = 0;
  1458. j < lpOPS->cLinkTypes;
  1459. (UINT&)pasteFlag *= 2, j++)
  1460. {
  1461. if ((lpOPS->arrPasteEntries[i].dwFlags & pasteFlag) &&
  1462. arrLinkTypesSupported[j])
  1463. {
  1464. fLinkTypeSupported = TRUE;
  1465. break;
  1466. }
  1467. }
  1468. }
  1469. fInsertFirst = FALSE;
  1470. if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfFileName
  1471. || lpOPS->arrPasteEntries[i].fmtetc.cfFormat == _g_cfLinkSource)
  1472. {
  1473. if (! fTryObjFmt)
  1474. {
  1475. fTryObjFmt = TRUE; // only use 1st object format
  1476. fInsertFirst = TRUE; // OLE obj format should always be 1st
  1477. }
  1478. else
  1479. {
  1480. continue; // already added an object format to list
  1481. }
  1482. }
  1483. // add to list if entry is marked TRUE
  1484. if (fLinkTypeSupported && lpOPS->arrPasteEntries[i].dwScratchSpace)
  1485. {
  1486. if (nDefFormat < 0)
  1487. nDefFormat = (fInsertFirst ? 0 : nItems);
  1488. else if (fInsertFirst)
  1489. nDefFormat++; // adjust for obj fmt inserted 1st in list
  1490. LPTSTR lpszBuf = (LPTSTR)GlobalLock(lpPS->hBuff);
  1491. if (lpszBuf)
  1492. {
  1493. UINT cchMax = (UINT)GlobalSize(lpPS->hBuff) / sizeof(TCHAR);
  1494. if (!FAddPasteListItem(hList, fInsertFirst, i, lpPS,
  1495. lpszBuf, cchMax, lpPS->szFullUserTypeNameLSD))
  1496. {
  1497. GlobalUnlock(lpPS->hBuff);
  1498. goto error;
  1499. }
  1500. GlobalUnlock(lpPS->hBuff);
  1501. }
  1502. nItems++;
  1503. }
  1504. } // end FOR
  1505. nItems = (int)SendMessage(hList, LB_GETCOUNT, 0, 0L);
  1506. // initialize selection to first format matched in list
  1507. if (nDefFormat >= 0)
  1508. lpPS->nPasteLinkListCurSel = nDefFormat;
  1509. cleanup:
  1510. // Clean up
  1511. // If no items have been added to the list box (none of the formats
  1512. // offered by the source matched those acceptable to the destination),
  1513. // return FALSE
  1514. if (nItems > 0)
  1515. return TRUE;
  1516. else
  1517. return FALSE;
  1518. error:
  1519. FreeListData(hList);
  1520. return FALSE;
  1521. }
  1522. /*
  1523. * FreeListData
  1524. *
  1525. * Purpose:
  1526. * Free the local memory associated with each list box item
  1527. *
  1528. * Parameters:
  1529. * hList HWND of the list
  1530. *
  1531. * Return Value:
  1532. * None
  1533. */
  1534. void FreeListData(HWND hList)
  1535. {
  1536. int nItems, i;
  1537. LPPASTELISTITEMDATA lpItemData;
  1538. nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L);
  1539. for (i = 0; i < nItems; i++)
  1540. {
  1541. lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
  1542. if ((LRESULT)lpItemData != LB_ERR)
  1543. OleStdFree((LPVOID)lpItemData);
  1544. }
  1545. }
  1546. /*
  1547. * FHasPercentS
  1548. *
  1549. * Purpose:
  1550. * Determines if string contains %s.
  1551. *
  1552. * Parameters:
  1553. * lpsz LPCSTR string in which occurence of '%s' is looked for
  1554. *
  1555. * Return Value:
  1556. * BOOL TRUE if %s is found, else FALSE.
  1557. */
  1558. BOOL FHasPercentS(LPCTSTR lpsz, LPPASTESPECIAL lpPS)
  1559. {
  1560. int n = 0;
  1561. LPTSTR lpszTmp;
  1562. if (!lpsz) return FALSE;
  1563. // Copy input string to buffer. This allows caller to pass a
  1564. // code-based string. Code segments may be swapped out in low memory situations
  1565. // and so code-based strings need to be copied before string elements can be accessed.
  1566. lpszTmp = (LPTSTR)GlobalLock(lpPS->hBuff);
  1567. UINT cchMax = (UINT)GlobalSize(lpPS->hBuff)/sizeof(TCHAR);
  1568. StringCchCopy(lpszTmp, cchMax, lpsz);
  1569. while (*lpszTmp)
  1570. {
  1571. if (*lpszTmp == '%')
  1572. {
  1573. lpszTmp = CharNext(lpszTmp);
  1574. if (*lpszTmp == 's') // if %s, return
  1575. {
  1576. GlobalUnlock(lpPS->hBuff);
  1577. return TRUE;
  1578. }
  1579. else if (*lpszTmp == '%') // if %%, skip to next character
  1580. lpszTmp = CharNext(lpszTmp);
  1581. }
  1582. else
  1583. lpszTmp = CharNext(lpszTmp);
  1584. }
  1585. GlobalUnlock(lpPS->hBuff);
  1586. return FALSE;
  1587. }
  1588. /*
  1589. * AllocateScratchMem
  1590. *
  1591. * Purpose:
  1592. * Allocates scratch memory for use by the PasteSpecial dialog. The memory is
  1593. * is used as the buffer for building up strings using wsprintf. Strings are built up
  1594. * using the buffer while inserting items into the Paste & PasteLink lists and while
  1595. * setting the help result text. It must be big enough to handle the string that results after
  1596. * replacing the %s in the lpstrFormatName and lpstrResultText in arrPasteEntries[]
  1597. * by the FullUserTypeName. It must also be big enough to build the dialog's result text
  1598. * after %s substitutions by the FullUserTypeName or the ApplicationName.
  1599. *
  1600. * Parameters:
  1601. * lpPS Paste Special Dialog Structure
  1602. *
  1603. * Return Value:
  1604. * HGLOBAL Handle to allocated global memory
  1605. */
  1606. HGLOBAL AllocateScratchMem(LPPASTESPECIAL lpPS)
  1607. {
  1608. LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
  1609. int nLen, i;
  1610. int nSubstitutedText = 0;
  1611. int nAlloc = 0;
  1612. // Get the maximum length of the FullUserTypeNames specified by OBJECTDESCRIPTOR
  1613. // and the LINKSRCDESCRIPTOR and the Application Name. Any of these may be substituted
  1614. // for %s in the result-text/list entries.
  1615. if (lpPS->szFullUserTypeNameOD)
  1616. nSubstitutedText = lstrlen(lpPS->szFullUserTypeNameOD);
  1617. if (lpPS->szFullUserTypeNameLSD)
  1618. nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szFullUserTypeNameLSD));
  1619. if (lpPS->szAppName)
  1620. nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szAppName));
  1621. // Get the maximum length of lpstrFormatNames & lpstrResultText in arrPasteEntries
  1622. nLen = 0;
  1623. for (i = 0; i < lpOPS->cPasteEntries; i++)
  1624. {
  1625. nLen = max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrFormatName));
  1626. nLen = max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrResultText));
  1627. }
  1628. // Get the maximum length of lpstrFormatNames and lpstrResultText after %s has
  1629. // been substituted (At most one %s can appear in each string).
  1630. // Add 1 to hold NULL terminator.
  1631. nAlloc = (nLen+nSubstitutedText+1)*sizeof(TCHAR);
  1632. // Allocate scratch memory to be used to build strings
  1633. // nAlloc is big enough to hold any of the lpstrResultText or lpstrFormatName in arrPasteEntries[]
  1634. // after %s substitution.
  1635. // We also need space to build up the help result text. 512 is the maximum length of the
  1636. // standard dialog help text before substitutions. 512+nAlloc is the maximum length
  1637. // after %s substition.
  1638. // SetPasteSpecialHelpResults() requires 4 such buffers to build up the result text
  1639. return GlobalAlloc(GHND, (DWORD)4*(512 * sizeof(TCHAR) + nAlloc));
  1640. }