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.

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