|
|
1.1 ! root 1: /************************************************************************* ! 2: ** ! 3: ** OLE 2 Sample Code ! 4: ** ! 5: ** clipbrd.c ! 6: ** ! 7: ** This file contains the major interfaces, methods and related support ! 8: ** functions for implementing clipboard data transfer. The code ! 9: ** contained in this file is used by BOTH the Container and Server ! 10: ** (Object) versions of the Outline sample code. ! 11: ** (see file dragdrop.c for Drag/Drop support implementation) ! 12: ** ! 13: ** OleDoc Object ! 14: ** exposed interfaces: ! 15: ** IDataObject ! 16: ** ! 17: ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved ! 18: ** ! 19: *************************************************************************/ ! 20: ! 21: #include "outline.h" ! 22: #include <enumfetc.h> ! 23: #include <geticon.h> ! 24: ! 25: OLEDBGDATA ! 26: ! 27: extern LPOUTLINEAPP g_lpApp; ! 28: ! 29: // REVIEW: should use string resource for messages ! 30: char ErrMsgPasting[] = "Could not paste data from clipboard!"; ! 31: char ErrMsgBadFmt[] = "Invalid format selected!"; ! 32: char ErrMsgPasteFailed[] = "Could not paste data from clipboard!"; ! 33: ! 34: ! 35: ! 36: /************************************************************************* ! 37: ** OleDoc::IDataObject interface implementation ! 38: *************************************************************************/ ! 39: ! 40: STDMETHODIMP OleDoc_DataObj_QueryInterface ( ! 41: LPDATAOBJECT lpThis, ! 42: REFIID riid, ! 43: LPVOID FAR* lplpvObj ! 44: ) ! 45: { ! 46: LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 47: ! 48: return OleDoc_QueryInterface((LPOLEDOC)lpOleDoc, riid, lplpvObj); ! 49: } ! 50: ! 51: ! 52: STDMETHODIMP_(ULONG) OleDoc_DataObj_AddRef(LPDATAOBJECT lpThis) ! 53: { ! 54: LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 55: ! 56: OleDbgAddRefMethod(lpThis, "IDataObject"); ! 57: ! 58: return OleDoc_AddRef((LPOLEDOC)lpOleDoc); ! 59: } ! 60: ! 61: ! 62: STDMETHODIMP_(ULONG) OleDoc_DataObj_Release (LPDATAOBJECT lpThis) ! 63: { ! 64: LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 65: ! 66: OleDbgReleaseMethod(lpThis, "IDataObject"); ! 67: ! 68: return OleDoc_Release((LPOLEDOC)lpOleDoc); ! 69: } ! 70: ! 71: ! 72: STDMETHODIMP OleDoc_DataObj_GetData ( ! 73: LPDATAOBJECT lpThis, ! 74: LPFORMATETC lpFormatetc, ! 75: LPSTGMEDIUM lpMedium ! 76: ) ! 77: { ! 78: LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 79: HRESULT hrErr; ! 80: ! 81: OLEDBG_BEGIN2("OleDoc_DataObj_GetData\r\n") ! 82: ! 83: #if defined( OLE_SERVER ) ! 84: // Call OLE Server specific version of this function ! 85: hrErr = ServerDoc_GetData((LPSERVERDOC)lpOleDoc, lpFormatetc, lpMedium); ! 86: ! 87: #elif defined( OLE_CNTR ) ! 88: // Call OLE Container specific version of this function ! 89: hrErr = ContainerDoc_GetData( ! 90: (LPCONTAINERDOC)lpOleDoc, ! 91: lpFormatetc, ! 92: lpMedium ! 93: ); ! 94: #endif ! 95: ! 96: OLEDBG_END2 ! 97: return hrErr; ! 98: } ! 99: ! 100: ! 101: STDMETHODIMP OleDoc_DataObj_GetDataHere ( ! 102: LPDATAOBJECT lpThis, ! 103: LPFORMATETC lpFormatetc, ! 104: LPSTGMEDIUM lpMedium ! 105: ) ! 106: { ! 107: LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 108: HRESULT hrErr; ! 109: ! 110: OLEDBG_BEGIN2("OleDoc_DataObj_GetDataHere\r\n") ! 111: ! 112: #if defined( OLE_SERVER ) ! 113: // Call OLE Server specific version of this function ! 114: hrErr = ServerDoc_GetDataHere( ! 115: (LPSERVERDOC)lpOleDoc, ! 116: lpFormatetc, ! 117: lpMedium ! 118: ); ! 119: ! 120: #elif defined( OLE_CNTR ) ! 121: // Call OLE Container specific version of this function ! 122: hrErr = ContainerDoc_GetDataHere( ! 123: (LPCONTAINERDOC)lpOleDoc, ! 124: lpFormatetc, ! 125: lpMedium ! 126: ); ! 127: #endif ! 128: ! 129: OLEDBG_END2 ! 130: return hrErr; ! 131: } ! 132: ! 133: ! 134: STDMETHODIMP OleDoc_DataObj_QueryGetData ( ! 135: LPDATAOBJECT lpThis, ! 136: LPFORMATETC lpFormatetc ! 137: ) ! 138: { ! 139: LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 140: HRESULT hrErr; ! 141: ! 142: OLEDBG_BEGIN2("OleDoc_DataObj_QueryGetData\r\n"); ! 143: ! 144: #if defined( OLE_SERVER ) ! 145: // Call OLE Server specific version of this function ! 146: hrErr = ServerDoc_QueryGetData((LPSERVERDOC)lpOleDoc, lpFormatetc); ! 147: ! 148: #elif defined( OLE_CNTR ) ! 149: // Call OLE Container specific version of this function ! 150: hrErr = ContainerDoc_QueryGetData((LPCONTAINERDOC)lpOleDoc, lpFormatetc); ! 151: #endif ! 152: ! 153: OLEDBG_END2 ! 154: return hrErr; ! 155: } ! 156: ! 157: ! 158: STDMETHODIMP OleDoc_DataObj_GetCanonicalFormatEtc( ! 159: LPDATAOBJECT lpThis, ! 160: LPFORMATETC lpformatetc, ! 161: LPFORMATETC lpformatetcOut ! 162: ) ! 163: { ! 164: OleDbgOut2("OleDoc_DataObj_GetCanonicalFormatEtc\r\n"); ! 165: ! 166: return ResultFromScode(E_NOTIMPL); ! 167: } ! 168: ! 169: ! 170: STDMETHODIMP OleDoc_DataObj_SetData ( ! 171: LPDATAOBJECT lpThis, ! 172: LPFORMATETC lpFormatetc, ! 173: LPSTGMEDIUM lpMedium, ! 174: BOOL fRelease ! 175: ) ! 176: { ! 177: LPOLEDOC lpOleDoc = ((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 178: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; ! 179: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 180: SCODE sc; ! 181: ! 182: OLEDBG_BEGIN2("OleDoc_DataObj_SetData\r\n") ! 183: ! 184: /* OLE2NOTE: a document that is used to transfer data (either via ! 185: ** the clipboard or drag/drop) does NOT accept SetData on ANY ! 186: ** format! ! 187: */ ! 188: if (lpOutlineDoc->m_fDataTransferDoc) { ! 189: sc = E_FAIL; ! 190: goto error; ! 191: } ! 192: ! 193: #if defined( OLE_SERVER ) ! 194: { ! 195: HRESULT hrErr; ! 196: ! 197: if (lpFormatetc->cfFormat == lpOutlineApp->m_cfOutline) { ! 198: ! 199: OLEDBG_BEGIN2("ServerDoc_SetData: CF_OUTLINE\r\n"); ! 200: ! 201: OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); ! 202: OutlineDoc_ClearAllLines(lpOutlineDoc); ! 203: OutlineDoc_PasteOutlineData(lpOutlineDoc,lpMedium->u.hGlobal,-1); ! 204: OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); ! 205: ! 206: OLEDBG_END3 ! 207: ! 208: } else if (lpFormatetc->cfFormat == CF_TEXT) { ! 209: ! 210: OLEDBG_BEGIN2("ServerDoc_SetData: CF_TEXT\r\n"); ! 211: ! 212: OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); ! 213: OutlineDoc_ClearAllLines(lpOutlineDoc); ! 214: OutlineDoc_PasteTextData(lpOutlineDoc,lpMedium->u.hGlobal,-1); ! 215: OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); ! 216: ! 217: OLEDBG_END3 ! 218: ! 219: } else { ! 220: sc = DATA_E_FORMATETC; ! 221: goto error; ! 222: } ! 223: ! 224: OLEDBG_END2 ! 225: return hrErr; ! 226: } ! 227: ! 228: #elif defined( OLE_CNTR ) ! 229: { ! 230: /* the Container-Only version of Outline does NOT offer ! 231: ** IDataObject interface from its User documents. this is ! 232: ** required by objects which can be embedded or linked. the ! 233: ** Container-only app only allows linking to its contained ! 234: ** objects, NOT the data of the container itself. ! 235: */ ! 236: OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n"); ! 237: sc = E_NOTIMPL; ! 238: goto error; ! 239: } ! 240: #endif ! 241: ! 242: error: ! 243: OLEDBG_END2 ! 244: return ResultFromScode(sc); ! 245: ! 246: } ! 247: ! 248: ! 249: STDMETHODIMP OleDoc_DataObj_EnumFormatEtc( ! 250: LPDATAOBJECT lpThis, ! 251: DWORD dwDirection, ! 252: LPENUMFORMATETC FAR* lplpenumFormatEtc ! 253: ) ! 254: { ! 255: LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 256: HRESULT hrErr; ! 257: ! 258: OLEDBG_BEGIN2("OleDoc_DataObj_EnumFormatEtc\r\n") ! 259: ! 260: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ ! 261: *lplpenumFormatEtc = NULL; ! 262: ! 263: #if defined( OLE_SERVER ) ! 264: /* OLE2NOTE: a user document only needs to enumerate the static list ! 265: ** of formats that are registered for our app in the ! 266: ** registration database. OLE provides a default enumerator ! 267: ** which enumerates from the registration database. this default ! 268: ** enumerator is requested by returning OLE_S_USEREG. it is NOT ! 269: ** required that a user document (ie. non-DataTransferDoc) ! 270: ** enumerate the OLE formats: CF_LINKSOURCE, CF_EMBEDSOURCE, or ! 271: ** CF_EMBEDDEDOBJECT. ! 272: */ ! 273: if (! ((LPOUTLINEDOC)lpOleDoc)->m_fDataTransferDoc) ! 274: return ResultFromScode(OLE_S_USEREG); ! 275: ! 276: // Call OLE Server specific version of this function ! 277: hrErr = ServerDoc_EnumFormatEtc( ! 278: (LPSERVERDOC)lpOleDoc, ! 279: dwDirection, ! 280: lplpenumFormatEtc ! 281: ); ! 282: #elif defined( OLE_CNTR ) ! 283: // Call OLE Container specific version of this function ! 284: hrErr = ContainerDoc_EnumFormatEtc( ! 285: (LPCONTAINERDOC)lpOleDoc, ! 286: dwDirection, ! 287: lplpenumFormatEtc ! 288: ); ! 289: #endif ! 290: ! 291: OLEDBG_END2 ! 292: return hrErr; ! 293: } ! 294: ! 295: ! 296: STDMETHODIMP OleDoc_DataObj_DAdvise( ! 297: LPDATAOBJECT lpThis, ! 298: FORMATETC FAR* lpFormatetc, ! 299: DWORD advf, ! 300: LPADVISESINK lpAdvSink, ! 301: DWORD FAR* lpdwConnection ! 302: ) ! 303: { ! 304: LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 305: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; ! 306: SCODE sc; ! 307: ! 308: OLEDBG_BEGIN2("OleDoc_DataObj_DAdvise\r\n") ! 309: ! 310: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ ! 311: *lpdwConnection = 0; ! 312: ! 313: /* OLE2NOTE: a document that is used to transfer data (either via ! 314: ** the clipboard or drag/drop) does NOT support Advise notifications. ! 315: */ ! 316: if (lpOutlineDoc->m_fDataTransferDoc) { ! 317: sc = OLE_E_ADVISENOTSUPPORTED; ! 318: goto error; ! 319: } ! 320: ! 321: #if defined( OLE_SERVER ) ! 322: { ! 323: HRESULT hrErr; ! 324: LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; ! 325: ! 326: if (lpServerDoc->m_lpDataAdviseHldr == NULL && ! 327: CreateDataAdviseHolder(&lpServerDoc->m_lpDataAdviseHldr) ! 328: != NOERROR) { ! 329: sc = E_OUTOFMEMORY; ! 330: goto error; ! 331: } ! 332: ! 333: OLEDBG_BEGIN2("IDataAdviseHolder::Advise called\r\n"); ! 334: hrErr = lpServerDoc->m_lpDataAdviseHldr->lpVtbl->Advise( ! 335: lpServerDoc->m_lpDataAdviseHldr, ! 336: (LPDATAOBJECT)&lpOleDoc->m_DataObject, ! 337: lpFormatetc, ! 338: advf, ! 339: lpAdvSink, ! 340: lpdwConnection ! 341: ); ! 342: OLEDBG_END2 ! 343: ! 344: OLEDBG_END2 ! 345: return hrErr; ! 346: } ! 347: ! 348: #elif defined( OLE_CNTR ) ! 349: { ! 350: /* the Container-Only version of Outline does NOT offer ! 351: ** IDataObject interface from its User documents. this is ! 352: ** required by objects which can be embedded or linked. the ! 353: ** Container-only app only allows linking to its contained ! 354: ** objects, NOT the data of the container itself. ! 355: */ ! 356: OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n"); ! 357: sc = E_NOTIMPL; ! 358: goto error; ! 359: } ! 360: #endif ! 361: ! 362: error: ! 363: OLEDBG_END2 ! 364: return ResultFromScode(sc); ! 365: } ! 366: ! 367: ! 368: STDMETHODIMP OleDoc_DataObj_DUnadvise(LPDATAOBJECT lpThis, DWORD dwConnection) ! 369: { ! 370: LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 371: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; ! 372: SCODE sc; ! 373: ! 374: OLEDBG_BEGIN2("OleDoc_DataObj_DUnadvise\r\n") ! 375: ! 376: /* OLE2NOTE: a document that is used to transfer data (either via ! 377: ** the clipboard or drag/drop) does NOT support Advise notifications. ! 378: */ ! 379: if (lpOutlineDoc->m_fDataTransferDoc) { ! 380: sc = OLE_E_ADVISENOTSUPPORTED; ! 381: goto error; ! 382: } ! 383: ! 384: #if defined( OLE_SERVER ) ! 385: { ! 386: LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; ! 387: HRESULT hrErr; ! 388: ! 389: if (lpServerDoc->m_lpDataAdviseHldr == NULL) { ! 390: sc = E_FAIL; ! 391: goto error; ! 392: } ! 393: ! 394: OLEDBG_BEGIN2("IDataAdviseHolder::Unadvise called\r\n"); ! 395: hrErr = lpServerDoc->m_lpDataAdviseHldr->lpVtbl->Unadvise( ! 396: lpServerDoc->m_lpDataAdviseHldr, ! 397: dwConnection ! 398: ); ! 399: OLEDBG_END2 ! 400: ! 401: OLEDBG_END2 ! 402: return hrErr; ! 403: } ! 404: #elif defined( OLE_CNTR ) ! 405: { ! 406: /* the Container-Only version of Outline does NOT offer ! 407: ** IDataObject interface from its User documents. this is ! 408: ** required by objects which can be embedded or linked. the ! 409: ** Container-only app only allows linking to its contained ! 410: ** objects, NOT the data of the container itself. ! 411: */ ! 412: OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n"); ! 413: sc = E_NOTIMPL; ! 414: goto error; ! 415: } ! 416: #endif ! 417: ! 418: error: ! 419: OLEDBG_END2 ! 420: return ResultFromScode(sc); ! 421: } ! 422: ! 423: ! 424: STDMETHODIMP OleDoc_DataObj_EnumDAdvise( ! 425: LPDATAOBJECT lpThis, ! 426: LPENUMSTATDATA FAR* lplpenumAdvise ! 427: ) ! 428: { ! 429: LPOLEDOC lpOleDoc=((struct CDocDataObjectImpl FAR*)lpThis)->lpOleDoc; ! 430: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; ! 431: SCODE sc; ! 432: ! 433: OLEDBG_BEGIN2("OleDoc_DataObj_EnumDAdvise\r\n") ! 434: ! 435: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ ! 436: *lplpenumAdvise = NULL; ! 437: ! 438: /* OLE2NOTE: a document that is used to transfer data (either via ! 439: ** the clipboard or drag/drop) does NOT support Advise notifications. ! 440: */ ! 441: if (lpOutlineDoc->m_fDataTransferDoc) { ! 442: sc = OLE_E_ADVISENOTSUPPORTED; ! 443: goto error; ! 444: } ! 445: ! 446: #if defined( OLE_SERVER ) ! 447: { ! 448: LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; ! 449: HRESULT hrErr; ! 450: ! 451: if (lpServerDoc->m_lpDataAdviseHldr == NULL) { ! 452: sc = E_FAIL; ! 453: goto error; ! 454: } ! 455: ! 456: OLEDBG_BEGIN2("IDataAdviseHolder::EnumAdvise called\r\n"); ! 457: hrErr = lpServerDoc->m_lpDataAdviseHldr->lpVtbl->EnumAdvise( ! 458: lpServerDoc->m_lpDataAdviseHldr, ! 459: lplpenumAdvise ! 460: ); ! 461: OLEDBG_END2 ! 462: ! 463: OLEDBG_END2 ! 464: return hrErr; ! 465: } ! 466: #elif defined( OLE_CNTR ) ! 467: { ! 468: /* the Container-Only version of Outline does NOT offer ! 469: ** IDataObject interface from its User documents. this is ! 470: ** required by objects which can be embedded or linked. the ! 471: ** Container-only app only allows linking to its contained ! 472: ** objects, NOT the data of the container itself. ! 473: */ ! 474: OleDbgAssertSz(0, "User documents do NOT support IDataObject\r\n"); ! 475: sc = E_NOTIMPL; ! 476: goto error; ! 477: } ! 478: #endif ! 479: ! 480: error: ! 481: OLEDBG_END2 ! 482: return ResultFromScode(sc); ! 483: } ! 484: ! 485: ! 486: ! 487: /************************************************************************* ! 488: ** OleDoc Supprt Functions common to both Container and Server versions ! 489: *************************************************************************/ ! 490: ! 491: /* OleDoc_PasteCommand ! 492: ** ------------------- ! 493: ** Paste default format data from the clipboard. ! 494: ** In this function we choose the highest fidelity format that the ! 495: ** source clipboard IDataObject* offers that we understand. ! 496: ** ! 497: ** OLE2NOTE: clipboard handling in an OLE 2.0 application is ! 498: ** different than normal Windows clipboard handling. Data from the ! 499: ** clipboard is retieved by getting the IDataObject* pointer ! 500: ** returned by calling OleGetClipboard. ! 501: */ ! 502: void OleDoc_PasteCommand(LPOLEDOC lpOleDoc) ! 503: { ! 504: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; ! 505: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 506: LPDATAOBJECT lpClipboardDataObj = NULL; ! 507: BOOL fLink = FALSE; ! 508: BOOL fLocalDataObj = FALSE; ! 509: BOOL fStatus; ! 510: HRESULT hrErr; ! 511: ! 512: hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj); ! 513: if (hrErr != NOERROR) ! 514: return; // Clipboard seems to be empty or can't be accessed ! 515: ! 516: OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); ! 517: ! 518: /* check if the data on the clipboard is local to our application ! 519: ** instance. ! 520: */ ! 521: if (lpOutlineApp->m_lpClipboardDoc) { ! 522: LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc; ! 523: if (lpClipboardDataObj == (LPDATAOBJECT)&lpOleDoc->m_DataObject) ! 524: fLocalDataObj = TRUE; ! 525: } ! 526: ! 527: fStatus = OleDoc_PasteFromData( ! 528: lpOleDoc, ! 529: lpClipboardDataObj, ! 530: fLocalDataObj, ! 531: fLink ! 532: ); ! 533: ! 534: OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); ! 535: ! 536: if (! fStatus) ! 537: OutlineApp_ErrorMessage(g_lpApp,"Could not paste data from clipboard!"); ! 538: ! 539: if (lpClipboardDataObj) ! 540: OleStdRelease((LPUNKNOWN)lpClipboardDataObj); ! 541: } ! 542: ! 543: ! 544: /* OleDoc_PasteSpecialCommand ! 545: ** -------------------------- ! 546: ** Allow the user to paste data in a particular format from the ! 547: ** clipboard. The paste special command displays a dialog to the ! 548: ** user that allows him to choose the format to be pasted from the ! 549: ** list of formats available. ! 550: ** ! 551: ** OLE2NOTE: the PasteSpecial dialog is one of the standard OLE 2.0 ! 552: ** UI dialogs for which the dialog is implemented and in the OLE2UI ! 553: ** library. ! 554: ** ! 555: ** OLE2NOTE: clipboard handling in an OLE 2.0 application is ! 556: ** different than normal Windows clipboard handling. Data from the ! 557: ** clipboard is retieved by getting the IDataObject* pointer ! 558: ** returned by calling OleGetClipboard. ! 559: */ ! 560: void OleDoc_PasteSpecialCommand(LPOLEDOC lpOleDoc) ! 561: { ! 562: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; ! 563: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 564: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 565: LPDATAOBJECT lpClipboardDataObj = NULL; ! 566: CLIPFORMAT cfFormat; ! 567: int nFmtEtc; ! 568: UINT uInt; ! 569: BOOL fLink = FALSE; ! 570: BOOL fLocalDataObj = FALSE; ! 571: BOOL fStatus; ! 572: HRESULT hrErr; ! 573: OLEUIPASTESPECIAL ouiPasteSpl; ! 574: BOOL fDisplayAsIcon; ! 575: ! 576: hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj); ! 577: if (hrErr != NOERROR) ! 578: return; // Clipboard seems to be empty or can't be accessed ! 579: ! 580: /* check if the data on the clipboard is local to our application ! 581: ** instance. ! 582: */ ! 583: if (lpOutlineApp->m_lpClipboardDoc) { ! 584: LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc; ! 585: if (lpClipboardDataObj == (LPDATAOBJECT)&lpOleDoc->m_DataObject) ! 586: fLocalDataObj = TRUE; ! 587: } ! 588: ! 589: /* Display the PasteSpecial dialog and allow the user to select the ! 590: ** format to paste. ! 591: */ ! 592: ouiPasteSpl.cbStruct = sizeof(OLEUIPASTESPECIAL); //Structure Size ! 593: ouiPasteSpl.dwFlags = PSF_SELECTPASTE | PSF_SHOWHELP; //IN-OUT: Flags ! 594: ouiPasteSpl.hWndOwner = lpOutlineApp->m_lpDoc->m_hWndDoc; //Owning window ! 595: ouiPasteSpl.lpszCaption = "Paste Special"; //Dialog caption bar contents ! 596: ouiPasteSpl.lpfnHook = NULL; //Hook callback ! 597: ouiPasteSpl.lCustData = 0; //Custom data to pass to hook ! 598: ouiPasteSpl.hInstance = NULL; //Instance for customized template name ! 599: ouiPasteSpl.lpszTemplate = NULL; //Customized template name ! 600: ouiPasteSpl.hResource = NULL; //Customized template handle ! 601: ! 602: ouiPasteSpl.arrPasteEntries = lpOleApp->m_arrPasteEntries; ! 603: ouiPasteSpl.cPasteEntries = lpOleApp->m_nPasteEntries; ! 604: ouiPasteSpl.lpSrcDataObj = lpClipboardDataObj; ! 605: ouiPasteSpl.arrLinkTypes = lpOleApp->m_arrLinkTypes; ! 606: ouiPasteSpl.cLinkTypes = lpOleApp->m_nLinkTypes; ! 607: ! 608: ! 609: OLEDBG_BEGIN3("OleUIPasteSpecial called\r\n") ! 610: uInt = OleUIPasteSpecial(&ouiPasteSpl); ! 611: OLEDBG_END3 ! 612: ! 613: fDisplayAsIcon = ! 614: (ouiPasteSpl.dwFlags & PSF_CHECKDISPLAYASICON ? TRUE : FALSE); ! 615: ! 616: if (uInt == OLEUI_OK) { ! 617: nFmtEtc = ouiPasteSpl.nSelectedIndex; ! 618: fLink = ouiPasteSpl.fLink; ! 619: ! 620: if (nFmtEtc < 0 || nFmtEtc >= lpOleApp->m_nPasteEntries) { ! 621: OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgBadFmt); ! 622: goto error; ! 623: } ! 624: ! 625: OutlineDoc_SetRedraw ( lpOutlineDoc, FALSE ); ! 626: ! 627: cfFormat = lpOleApp->m_arrPasteEntries[nFmtEtc].fmtetc.cfFormat; ! 628: ! 629: fStatus = OleDoc_PasteFormatFromData( ! 630: lpOleDoc, ! 631: cfFormat, ! 632: lpClipboardDataObj, ! 633: fLocalDataObj, ! 634: fLink, ! 635: fDisplayAsIcon, ! 636: ouiPasteSpl.hMetaPict ! 637: ); ! 638: ! 639: OutlineDoc_SetRedraw ( lpOutlineDoc, TRUE ); ! 640: ! 641: if (! fStatus) { ! 642: OutlineApp_ErrorMessage(lpOutlineApp, ErrMsgPasteFailed); ! 643: goto error; ! 644: } ! 645: ! 646: if (ouiPasteSpl.hMetaPict) { ! 647: // clean up metafile ! 648: OleUIMetafilePictIconFree(ouiPasteSpl.hMetaPict); ! 649: } ! 650: ! 651: } ! 652: ! 653: if (lpClipboardDataObj) ! 654: OleStdRelease((LPUNKNOWN)lpClipboardDataObj); ! 655: ! 656: return; ! 657: ! 658: error: ! 659: ! 660: if (lpClipboardDataObj) ! 661: OleStdRelease((LPUNKNOWN)lpClipboardDataObj); ! 662: ! 663: if (uInt == OLEUI_OK && ouiPasteSpl.hMetaPict) ! 664: // clean up metafile ! 665: OleUIMetafilePictIconFree(ouiPasteSpl.hMetaPict); ! 666: } ! 667: ! 668: ! 669: /* OleDoc_PasteFromData ! 670: ** -------------------- ! 671: ** ! 672: ** Paste data from an IDataObject*. The IDataObject* may come from ! 673: ** the clipboard (GetClipboard) or from a drag/drop operation. ! 674: ** In this function we choose the best format that we prefer. ! 675: ** ! 676: ** Returns TRUE if data was successfully pasted. ! 677: ** FALSE if data could not be pasted. ! 678: */ ! 679: ! 680: BOOL OleDoc_PasteFromData( ! 681: LPOLEDOC lpOleDoc, ! 682: LPDATAOBJECT lpSrcDataObj, ! 683: BOOL fLocalDataObj, ! 684: BOOL fLink ! 685: ) ! 686: { ! 687: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 688: CLIPFORMAT cfFormat; ! 689: BOOL fDisplayAsIcon = FALSE; ! 690: HGLOBAL hMem = NULL; ! 691: HGLOBAL hMetaPict = NULL; ! 692: STGMEDIUM medium; ! 693: ! 694: if (fLink) { ! 695: #if defined( OLE_SERVER ) ! 696: ! 697: return FALSE; // server version of app does NOT support links ! 698: ! 699: #elif defined( OLE_CNTR ) ! 700: ! 701: // container version of app only supports OLE object type links ! 702: cfFormat = lpOleApp->m_cfLinkSource; ! 703: #endif ! 704: ! 705: } else { ! 706: ! 707: int nFmtEtc; ! 708: ! 709: nFmtEtc = OleStdGetPriorityClipboardFormat( ! 710: lpSrcDataObj, ! 711: lpOleApp->m_arrPasteEntries, ! 712: lpOleApp->m_nPasteEntries ! 713: ); ! 714: ! 715: if (nFmtEtc < 0) ! 716: return FALSE; // there is no format we like ! 717: ! 718: cfFormat = lpOleApp->m_arrPasteEntries[nFmtEtc].fmtetc.cfFormat; ! 719: } ! 720: ! 721: /* OLE2NOTE: we need to check what dwDrawAspect is being ! 722: ** transfered. if the data is an object that is displayed as an ! 723: ** icon in the source, then we want to keep it as an icon. the ! 724: ** aspect the object is displayed in at the source is transfered ! 725: ** via the CF_OBJECTDESCRIPTOR format for a Paste operation. ! 726: */ ! 727: if (hMem = OleStdGetData( ! 728: lpSrcDataObj, ! 729: lpOleApp->m_cfObjectDescriptor, ! 730: NULL, ! 731: DVASPECT_CONTENT, ! 732: (LPSTGMEDIUM)&medium)) { ! 733: LPOBJECTDESCRIPTOR lpOD = GlobalLock(hMem); ! 734: fDisplayAsIcon = (lpOD->dwDrawAspect == DVASPECT_ICON ? TRUE : FALSE); ! 735: GlobalUnlock(hMem); ! 736: ReleaseStgMedium((LPSTGMEDIUM)&medium); // equiv to GlobalFree ! 737: ! 738: if (fDisplayAsIcon) { ! 739: hMetaPict = OleStdGetData( ! 740: lpSrcDataObj, ! 741: CF_METAFILEPICT, ! 742: NULL, ! 743: DVASPECT_ICON, ! 744: (LPSTGMEDIUM)&medium ! 745: ); ! 746: if (hMetaPict == NULL) ! 747: fDisplayAsIcon = FALSE; // give up; failed to get icon MFP ! 748: } ! 749: } ! 750: ! 751: return OleDoc_PasteFormatFromData( ! 752: lpOleDoc, ! 753: cfFormat, ! 754: lpSrcDataObj, ! 755: fLocalDataObj, ! 756: fLink, ! 757: fDisplayAsIcon, ! 758: hMetaPict ! 759: ); ! 760: ! 761: if (hMetaPict) ! 762: ReleaseStgMedium((LPSTGMEDIUM)&medium); // properly free METAFILEPICT ! 763: } ! 764: ! 765: ! 766: /* OleDoc_PasteFormatFromData ! 767: ** -------------------------- ! 768: ** ! 769: ** Paste a particular data format from a IDataObject*. The ! 770: ** IDataObject* may come from the clipboard (GetClipboard) or from a ! 771: ** drag/drop operation. ! 772: ** ! 773: ** Returns TRUE if data was successfully pasted. ! 774: ** FALSE if data could not be pasted. ! 775: */ ! 776: ! 777: BOOL OleDoc_PasteFormatFromData( ! 778: LPOLEDOC lpOleDoc, ! 779: CLIPFORMAT cfFormat, ! 780: LPDATAOBJECT lpSrcDataObj, ! 781: BOOL fLocalDataObj, ! 782: BOOL fLink, ! 783: BOOL fDisplayAsIcon, ! 784: HGLOBAL hMetaPict ! 785: ) ! 786: { ! 787: #if defined( OLE_SERVER ) ! 788: ! 789: /* call server specific version of the function. */ ! 790: return ServerDoc_PasteFormatFromData( ! 791: (LPSERVERDOC)lpOleDoc, ! 792: cfFormat, ! 793: lpSrcDataObj, ! 794: fLocalDataObj, ! 795: fLink ! 796: ); ! 797: ! 798: #elif defined( OLE_CNTR ) ! 799: ! 800: /* call container specific version of the function. */ ! 801: return ContainerDoc_PasteFormatFromData( ! 802: (LPCONTAINERDOC)lpOleDoc, ! 803: cfFormat, ! 804: lpSrcDataObj, ! 805: fLocalDataObj, ! 806: fLink, ! 807: fDisplayAsIcon, ! 808: hMetaPict ! 809: ); ! 810: ! 811: #endif ! 812: } ! 813: ! 814: ! 815: /* OleDoc_QueryPasteFromData ! 816: ** ------------------------- ! 817: ** ! 818: ** Check if the IDataObject* offers data in a format that we can ! 819: ** paste. The IDataObject* may come from the clipboard ! 820: ** (GetClipboard) or from a drag/drop operation. ! 821: ** ! 822: ** Returns TRUE if paste can be performed ! 823: ** FALSE if paste is not possible. ! 824: */ ! 825: ! 826: BOOL OleDoc_QueryPasteFromData( ! 827: LPOLEDOC lpOleDoc, ! 828: LPDATAOBJECT lpSrcDataObj, ! 829: BOOL fLink ! 830: ) ! 831: { ! 832: #if defined( OLE_SERVER ) ! 833: ! 834: return ServerDoc_QueryPasteFromData( ! 835: (LPSERVERDOC) lpOleDoc, ! 836: lpSrcDataObj, ! 837: fLink ! 838: ); ! 839: ! 840: #elif defined( OLE_CNTR ) ! 841: ! 842: return ContainerDoc_QueryPasteFromData( ! 843: (LPCONTAINERDOC) lpOleDoc, ! 844: lpSrcDataObj, ! 845: fLink ! 846: ); ! 847: ! 848: #endif ! 849: } ! 850: ! 851: ! 852: /* OleDoc_GetExtent ! 853: * ---------------- ! 854: * ! 855: * Get the extent (width, height) of the entire document in Himetric. ! 856: */ ! 857: void OleDoc_GetExtent(LPOLEDOC lpOleDoc, LPSIZEL lpsizel) ! 858: { ! 859: LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; ! 860: ! 861: LineList_CalcSelExtentInHimetric(lpLL, NULL, lpsizel); ! 862: } ! 863: ! 864: ! 865: /* OleDoc_GetObjectDescriptorData ! 866: * ------------------------------ ! 867: * ! 868: * Return a handle to an object's data in CF_OBJECTDESCRIPTOR form ! 869: * ! 870: */ ! 871: HGLOBAL OleDoc_GetObjectDescriptorData(LPOLEDOC lpOleDoc, LPLINERANGE lplrSel) ! 872: { ! 873: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpOleDoc; ! 874: ! 875: /* Only our data transfer doc renders CF_OBJECTDESCRIPTOR */ ! 876: OleDbgAssert(lpOutlineDoc->m_fDataTransferDoc); ! 877: ! 878: #if defined( OLE_SERVER ) ! 879: { ! 880: LPSERVERDOC lpServerDoc = (LPSERVERDOC)lpOleDoc; ! 881: SIZEL sizel; ! 882: POINTL pointl; ! 883: LPSTR lpszSrcOfCopy = NULL; ! 884: IBindCtx FAR *pbc = NULL; ! 885: HGLOBAL hObjDesc; ! 886: DWORD dwStatus = 0; ! 887: LPOUTLINEDOC lpSrcDocOfCopy=(LPOUTLINEDOC)lpOleDoc->m_lpSrcDocOfCopy; ! 888: LPMONIKER lpSrcMonikerOfCopy = ServerDoc_GetSelFullMoniker( ! 889: (LPSERVERDOC)lpOleDoc->m_lpSrcDocOfCopy, ! 890: &lpServerDoc->m_lrSrcSelOfCopy, ! 891: GETMONIKER_TEMPFORUSER ! 892: ); ! 893: ! 894: SvrDoc_OleObj_GetMiscStatus( ! 895: (LPOLEOBJECT)&lpServerDoc->m_OleObject, ! 896: DVASPECT_CONTENT, ! 897: &dwStatus ! 898: ); ! 899: ! 900: OleDoc_GetExtent(lpOleDoc, &sizel); ! 901: pointl.x = pointl.y = 0; ! 902: ! 903: if (lpSrcMonikerOfCopy) { ! 904: CreateBindCtx(0, (LPBC FAR*)&pbc); ! 905: lpSrcMonikerOfCopy->lpVtbl->GetDisplayName( ! 906: lpSrcMonikerOfCopy, pbc, NULL, &lpszSrcOfCopy); ! 907: pbc->lpVtbl->Release(pbc); ! 908: lpSrcMonikerOfCopy->lpVtbl->Release(lpSrcMonikerOfCopy); ! 909: } else { ! 910: /* this document has no moniker; use our FullUserTypeName ! 911: ** as the description of the source of copy. ! 912: */ ! 913: lpszSrcOfCopy = FULLUSERTYPENAME; ! 914: } ! 915: ! 916: hObjDesc = OleStdGetObjectDescriptorData( ! 917: CLSID_APP, ! 918: DVASPECT_CONTENT, ! 919: sizel, ! 920: pointl, ! 921: dwStatus, ! 922: FULLUSERTYPENAME, ! 923: lpszSrcOfCopy ! 924: ); ! 925: ! 926: if (lpSrcMonikerOfCopy && lpszSrcOfCopy) ! 927: OleStdFreeString(lpszSrcOfCopy, NULL); ! 928: return hObjDesc; ! 929: ! 930: } ! 931: #elif defined( OLE_CNTR ) ! 932: { ! 933: LPCONTAINERDOC lpContainerDoc = (LPCONTAINERDOC)lpOleDoc; ! 934: LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpOleDoc)->m_LineList; ! 935: LPCONTAINERLINE lpContainerLine; ! 936: HGLOBAL hObjDesc; ! 937: BOOL fSelIsOleObject = FALSE; ! 938: LPOLEOBJECT lpOleObj; ! 939: SIZEL sizel; ! 940: POINTL pointl; ! 941: ! 942: if ( lpLL->m_nNumLines == 1 ) { ! 943: fSelIsOleObject = ContainerDoc_IsSelAnOleObject( ! 944: lpContainerDoc, ! 945: &IID_IOleObject, ! 946: (LPUNKNOWN FAR*)&lpOleObj, ! 947: NULL, /* we don't need the line index */ ! 948: (LPCONTAINERLINE FAR*)&lpContainerLine ! 949: ); ! 950: } ! 951: ! 952: pointl.x = pointl.y = 0; ! 953: ! 954: if (fSelIsOleObject) { ! 955: /* OLE2NOTE: a single OLE object is being transfered via ! 956: ** this DataTransferDoc. we need to generate the ! 957: ** CF_ObjectDescrioptor which describes the OLE object. ! 958: */ ! 959: ! 960: LPOUTLINEDOC lpSrcOutlineDoc = ! 961: (LPOUTLINEDOC)lpOleDoc->m_lpSrcDocOfCopy; ! 962: LPSTR lpszSrcOfCopy = lpSrcOutlineDoc->m_szFileName; ! 963: BOOL fFreeSrcOfCopy = FALSE; ! 964: ! 965: /* if the object copied can be linked to then get a ! 966: ** TEMPFORUSER form of the moniker which identifies the ! 967: ** source of copy. we do not want to force the ! 968: ** assignment of the moniker until CF_LINKSOURCE is ! 969: ** rendered. ! 970: ** if the object copied can not be a link source then use ! 971: ** the source filename to identify the source of copy. ! 972: ** there is no need to generate a moniker for the object ! 973: ** copied. ! 974: */ ! 975: if (lpOleDoc->m_fLinkSourceAvail && ! 976: lpContainerDoc->m_lpSrcContainerLine) { ! 977: LPBINDCTX pbc = NULL; ! 978: LPMONIKER lpSrcMonikerOfCopy = ContainerLine_GetFullMoniker( ! 979: lpContainerDoc->m_lpSrcContainerLine, ! 980: GETMONIKER_TEMPFORUSER ! 981: ); ! 982: if (lpSrcMonikerOfCopy) { ! 983: CreateBindCtx(0, (LPBC FAR*)&pbc); ! 984: if (pbc != NULL) { ! 985: lpSrcMonikerOfCopy->lpVtbl->GetDisplayName( ! 986: lpSrcMonikerOfCopy, pbc, NULL,&lpszSrcOfCopy); ! 987: pbc->lpVtbl->Release(pbc); ! 988: fFreeSrcOfCopy = TRUE; ! 989: } ! 990: lpSrcMonikerOfCopy->lpVtbl->Release(lpSrcMonikerOfCopy); ! 991: } ! 992: } ! 993: ! 994: hObjDesc = OleStdGetObjectDescriptorDataFromOleObject( ! 995: lpOleObj, ! 996: lpszSrcOfCopy, ! 997: lpContainerLine->m_dwDrawAspect, ! 998: pointl ! 999: ); ! 1000: ! 1001: if (fFreeSrcOfCopy && lpszSrcOfCopy) ! 1002: OleStdFreeString(lpszSrcOfCopy, NULL); ! 1003: OleStdRelease((LPUNKNOWN)lpOleObj); ! 1004: return hObjDesc; ! 1005: } else { ! 1006: /* OLE2NOTE: the data being transfered via this ! 1007: ** DataTransferDoc is NOT a single OLE object. thus in ! 1008: ** this case the CF_ObjectDescriptor data should ! 1009: ** describe our container app itself. ! 1010: */ ! 1011: OleDoc_GetExtent(lpOleDoc, &sizel); ! 1012: return OleStdGetObjectDescriptorData( ! 1013: CLSID_NULL, /* not used if no object formats */ ! 1014: DVASPECT_CONTENT, ! 1015: sizel, ! 1016: pointl, ! 1017: 0, ! 1018: NULL, /* UserTypeName not used if no obj fmt's */ ! 1019: FULLUSERTYPENAME /* string to identify source of copy */ ! 1020: ); ! 1021: ! 1022: } ! 1023: } ! 1024: #endif ! 1025: } ! 1026: ! 1027: ! 1028: #if defined( OLE_SERVER ) ! 1029: ! 1030: /************************************************************************* ! 1031: ** ServerDoc Supprt Functions Used by Server versions ! 1032: *************************************************************************/ ! 1033: ! 1034: ! 1035: /* ServerDoc_PasteFormatFromData ! 1036: ** ----------------------------- ! 1037: ** ! 1038: ** Paste a particular data format from a IDataObject*. The ! 1039: ** IDataObject* may come from the clipboard (GetClipboard) or from a ! 1040: ** drag/drop operation. ! 1041: ** ! 1042: ** NOTE: fLink is specified then FALSE if returned because the ! 1043: ** Server only version of the app can not support links. ! 1044: ** ! 1045: ** Returns TRUE if data was successfully pasted. ! 1046: ** FALSE if data could not be pasted. ! 1047: */ ! 1048: BOOL ServerDoc_PasteFormatFromData( ! 1049: LPSERVERDOC lpServerDoc, ! 1050: CLIPFORMAT cfFormat, ! 1051: LPDATAOBJECT lpSrcDataObj, ! 1052: BOOL fLocalDataObj, ! 1053: BOOL fLink ! 1054: ) ! 1055: { ! 1056: LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpServerDoc)->m_LineList; ! 1057: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 1058: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 1059: int nIndex; ! 1060: int nCount = 0; ! 1061: HGLOBAL hData; ! 1062: STGMEDIUM medium; ! 1063: LINERANGE lrSel; ! 1064: ! 1065: if (LineList_GetCount(lpLL) == 0) ! 1066: nIndex = -1; // pasting to empty list ! 1067: else ! 1068: nIndex=LineList_GetFocusLineIndex(lpLL); ! 1069: ! 1070: if (fLink) { ! 1071: /* We should paste a Link to the data, but we do not support links */ ! 1072: return FALSE; ! 1073: ! 1074: } else { ! 1075: ! 1076: if (cfFormat == lpOutlineApp->m_cfOutline) { ! 1077: ! 1078: hData = OleStdGetData( ! 1079: lpSrcDataObj, ! 1080: lpOutlineApp->m_cfOutline, ! 1081: NULL, ! 1082: DVASPECT_CONTENT, ! 1083: (LPSTGMEDIUM)&medium ! 1084: ); ! 1085: if (hData == NULL) ! 1086: return FALSE; ! 1087: ! 1088: nCount = OutlineDoc_PasteOutlineData( ! 1089: (LPOUTLINEDOC)lpServerDoc, ! 1090: hData, ! 1091: nIndex ! 1092: ); ! 1093: // OLE2NOTE: we must free data handle by releasing the medium ! 1094: ReleaseStgMedium((LPSTGMEDIUM)&medium); ! 1095: ! 1096: } else if(cfFormat == CF_TEXT) { ! 1097: ! 1098: hData = OleStdGetData( ! 1099: lpSrcDataObj, ! 1100: CF_TEXT, ! 1101: NULL, ! 1102: DVASPECT_CONTENT, ! 1103: (LPSTGMEDIUM)&medium ! 1104: ); ! 1105: if (hData == NULL) ! 1106: return FALSE; ! 1107: ! 1108: nCount = OutlineDoc_PasteTextData( ! 1109: (LPOUTLINEDOC)lpServerDoc, ! 1110: hData, ! 1111: nIndex ! 1112: ); ! 1113: // OLE2NOTE: we must free data handle by releasing the medium ! 1114: ReleaseStgMedium((LPSTGMEDIUM)&medium); ! 1115: } ! 1116: } ! 1117: ! 1118: lrSel.m_nEndLine = nIndex + 1; ! 1119: lrSel.m_nStartLine = nIndex + nCount; ! 1120: LineList_SetSel(lpLL, &lrSel); ! 1121: return TRUE; ! 1122: } ! 1123: ! 1124: ! 1125: /* ServerDoc_QueryPasteFromData ! 1126: ** ---------------------------- ! 1127: ** ! 1128: ** Check if the IDataObject* offers data in a format that we can ! 1129: ** paste. The IDataObject* may come from the clipboard ! 1130: ** (GetClipboard) or from a drag/drop operation. ! 1131: ** In this function we look if one of the following formats is ! 1132: ** offered: ! 1133: ** CF_OUTLINE ! 1134: ** CF_TEXT ! 1135: ** ! 1136: ** NOTE: fLink is specified then FALSE if returned because the ! 1137: ** Server only version of the app can not support links. ! 1138: ** ! 1139: ** Returns TRUE if paste can be performed ! 1140: ** FALSE if paste is not possible. ! 1141: */ ! 1142: BOOL ServerDoc_QueryPasteFromData( ! 1143: LPSERVERDOC lpServerDoc, ! 1144: LPDATAOBJECT lpSrcDataObj, ! 1145: BOOL fLink ! 1146: ) ! 1147: { ! 1148: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 1149: ! 1150: if (fLink) { ! 1151: /* we do not support links */ ! 1152: return FALSE; ! 1153: ! 1154: } else { ! 1155: ! 1156: int nFmtEtc; ! 1157: ! 1158: nFmtEtc = OleStdGetPriorityClipboardFormat( ! 1159: lpSrcDataObj, ! 1160: lpOleApp->m_arrPasteEntries, ! 1161: lpOleApp->m_nPasteEntries ! 1162: ); ! 1163: ! 1164: if (nFmtEtc < 0) ! 1165: return FALSE; // there is no format we like ! 1166: } ! 1167: ! 1168: return TRUE; ! 1169: } ! 1170: ! 1171: ! 1172: /* ServerDoc_GetData ! 1173: * ----------------- ! 1174: * ! 1175: * Render data from the document on a CALLEE allocated STGMEDIUM. ! 1176: * This routine is called via IDataObject::GetData. ! 1177: */ ! 1178: ! 1179: HRESULT ServerDoc_GetData ( ! 1180: LPSERVERDOC lpServerDoc, ! 1181: LPFORMATETC lpformatetc, ! 1182: LPSTGMEDIUM lpMedium ! 1183: ) ! 1184: { ! 1185: LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; ! 1186: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 1187: LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; ! 1188: LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; ! 1189: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; ! 1190: HRESULT hrErr; ! 1191: SCODE sc; ! 1192: ! 1193: // OLE2NOTE: we must set out pointer parameters to NULL ! 1194: lpMedium->pUnkForRelease = NULL; ! 1195: ! 1196: /* OLE2NOTE: we must make sure to set all out parameters to NULL. */ ! 1197: lpMedium->tymed = TYMED_NULL; ! 1198: lpMedium->pUnkForRelease = NULL; // we transfer ownership to caller ! 1199: lpMedium->u.hGlobal = NULL; ! 1200: ! 1201: if(lpformatetc->cfFormat == lpOutlineApp->m_cfOutline) { ! 1202: // Verify caller asked for correct medium ! 1203: if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { ! 1204: sc = DATA_E_FORMATETC; ! 1205: goto error; ! 1206: } ! 1207: lpMedium->u.hGlobal = OutlineDoc_GetOutlineData (lpOutlineDoc,NULL); ! 1208: if (! lpMedium->u.hGlobal) { ! 1209: sc = E_OUTOFMEMORY; ! 1210: goto error; ! 1211: } ! 1212: ! 1213: lpMedium->tymed = TYMED_HGLOBAL; ! 1214: OleDbgOut3("ServerDoc_GetData: rendered CF_OUTLINE\r\n"); ! 1215: return NOERROR; ! 1216: ! 1217: } else if (lpformatetc->cfFormat == CF_METAFILEPICT && ! 1218: (lpformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_DOCPRINT)) ) { ! 1219: // Verify caller asked for correct medium ! 1220: if (!(lpformatetc->tymed & TYMED_MFPICT)) { ! 1221: sc = DATA_E_FORMATETC; ! 1222: goto error; ! 1223: } ! 1224: ! 1225: lpMedium->u.hGlobal = ServerDoc_GetMetafilePictData(lpServerDoc,NULL); ! 1226: if (! lpMedium->u.hGlobal) { ! 1227: sc = E_OUTOFMEMORY; ! 1228: goto error; ! 1229: } ! 1230: ! 1231: lpMedium->tymed = TYMED_MFPICT; ! 1232: OleDbgOut3("ServerDoc_GetData: rendered CF_METAFILEPICT\r\n"); ! 1233: return NOERROR; ! 1234: ! 1235: } else if (lpformatetc->cfFormat == CF_METAFILEPICT && ! 1236: (lpformatetc->dwAspect & DVASPECT_ICON) ) { ! 1237: CLSID clsid; ! 1238: // Verify caller asked for correct medium ! 1239: if (!(lpformatetc->tymed & TYMED_MFPICT)) { ! 1240: sc = DATA_E_FORMATETC; ! 1241: goto error; ! 1242: } ! 1243: ! 1244: /* OLE2NOTE: we should return the default icon for our class. ! 1245: ** we must be carefull to use the correct CLSID here. ! 1246: ** if we are currently preforming a "TreatAs (aka. ActivateAs)" ! 1247: ** operation then we need to use the class of the object ! 1248: ** written in the storage of the object. otherwise we would ! 1249: ** use our own class id. ! 1250: */ ! 1251: if (ServerDoc_GetClassID(lpServerDoc, (LPCLSID)&clsid) != NOERROR) { ! 1252: sc = DATA_E_FORMATETC; ! 1253: goto error; ! 1254: } ! 1255: ! 1256: lpMedium->u.hGlobal=GetIconOfClass(g_lpApp->m_hInst,(REFCLSID)&clsid, NULL, FALSE); ! 1257: if (! lpMedium->u.hGlobal) { ! 1258: sc = E_OUTOFMEMORY; ! 1259: goto error; ! 1260: } ! 1261: ! 1262: lpMedium->tymed = TYMED_MFPICT; ! 1263: OleDbgOut3("ServerDoc_GetData: rendered CF_METAFILEPICT (icon)\r\n"); ! 1264: return NOERROR; ! 1265: ! 1266: } else if (lpformatetc->cfFormat == CF_TEXT) { ! 1267: // Verify caller asked for correct medium ! 1268: if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { ! 1269: sc = DATA_E_FORMATETC; ! 1270: goto error; ! 1271: } ! 1272: ! 1273: lpMedium->u.hGlobal = OutlineDoc_GetTextData ( ! 1274: (LPOUTLINEDOC)lpServerDoc, ! 1275: NULL ! 1276: ); ! 1277: if (! lpMedium->u.hGlobal) { ! 1278: sc = E_OUTOFMEMORY; ! 1279: goto error; ! 1280: } ! 1281: ! 1282: lpMedium->tymed = TYMED_HGLOBAL; ! 1283: OleDbgOut3("ServerDoc_GetData: rendered CF_TEXT\r\n"); ! 1284: return NOERROR; ! 1285: } ! 1286: ! 1287: /* the above are the only formats supports by a user document (ie. ! 1288: ** a non-data transfer doc). if the document is used for ! 1289: ** purposes of data transfer, then additional formats are offered. ! 1290: */ ! 1291: if (! lpOutlineDoc->m_fDataTransferDoc) { ! 1292: sc = DATA_E_FORMATETC; ! 1293: goto error; ! 1294: } ! 1295: ! 1296: /* OLE2NOTE: ObjectDescriptor and LinkSrcDescriptor will ! 1297: ** contain the same data for the pure container and pure server ! 1298: ** type applications. only a container/server application may ! 1299: ** have different content for ObjectDescriptor and ! 1300: ** LinkSrcDescriptor. if a container/server copies a link for ! 1301: ** example, then the ObjectDescriptor would give the class ! 1302: ** of the link source but the LinkSrcDescriptor would give the ! 1303: ** class of the container/server itself. in this situation if a ! 1304: ** paste operation occurs, an equivalent link is pasted, but if ! 1305: ** a pastelink operation occurs, then a link to a pseudo object ! 1306: ** in the container/server is created. ! 1307: */ ! 1308: if (lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor || ! 1309: (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor && ! 1310: lpOleDoc->m_fLinkSourceAvail)) { ! 1311: // Verify caller asked for correct medium ! 1312: if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { ! 1313: sc = DATA_E_FORMATETC; ! 1314: goto error; ! 1315: } ! 1316: ! 1317: lpMedium->u.hGlobal = OleDoc_GetObjectDescriptorData ( ! 1318: (LPOLEDOC)lpServerDoc, ! 1319: NULL ! 1320: ); ! 1321: if (! lpMedium->u.hGlobal) { ! 1322: sc = E_OUTOFMEMORY; ! 1323: goto error; ! 1324: } ! 1325: ! 1326: lpMedium->tymed = TYMED_HGLOBAL; ! 1327: OleDbgOut3("ServerDoc_GetData: rendered CF_OBJECTDESCRIPTOR\r\n"); ! 1328: return NOERROR; ! 1329: ! 1330: } else if (lpformatetc->cfFormat == lpOleApp->m_cfEmbedSource) { ! 1331: hrErr = OleStdGetOleObjectData( ! 1332: (LPPERSISTSTORAGE)&lpServerDoc->m_PersistStorage, ! 1333: lpformatetc, ! 1334: lpMedium, ! 1335: FALSE /* fUseMemory -- (use file-base stg) */ ! 1336: ! 1337: ); ! 1338: if (hrErr != NOERROR) { ! 1339: sc = GetScode(hrErr); ! 1340: goto error; ! 1341: } ! 1342: OleDbgOut3("ServerDoc_GetData: rendered CF_EMBEDSOURCE\r\n"); ! 1343: return NOERROR; ! 1344: ! 1345: } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) { ! 1346: if (lpOleDoc->m_fLinkSourceAvail) { ! 1347: LPMONIKER lpmk; ! 1348: ! 1349: lpmk = ServerDoc_GetSelFullMoniker( ! 1350: (LPSERVERDOC)lpOleDoc->m_lpSrcDocOfCopy, ! 1351: &lpServerDoc->m_lrSrcSelOfCopy, ! 1352: GETMONIKER_FORCEASSIGN ! 1353: ); ! 1354: if (lpmk) { ! 1355: hrErr = OleStdGetLinkSourceData( ! 1356: lpmk, ! 1357: (LPCLSID)&CLSID_APP, ! 1358: lpformatetc, ! 1359: lpMedium ! 1360: ); ! 1361: OleStdRelease((LPUNKNOWN)lpmk); ! 1362: if (hrErr != NOERROR) { ! 1363: sc = GetScode(hrErr); ! 1364: goto error; ! 1365: } ! 1366: OleDbgOut3("ServerDoc_GetData: rendered CF_LINKSOURCE\r\n"); ! 1367: return NOERROR; ! 1368: ! 1369: } else { ! 1370: sc = E_FAIL; ! 1371: goto error; ! 1372: } ! 1373: } else { ! 1374: sc = DATA_E_FORMATETC; ! 1375: goto error; ! 1376: } ! 1377: ! 1378: } else { ! 1379: sc = DATA_E_FORMATETC; ! 1380: goto error; ! 1381: } ! 1382: ! 1383: return NOERROR; ! 1384: ! 1385: error: ! 1386: return ResultFromScode(sc); ! 1387: } ! 1388: ! 1389: ! 1390: /* ServerDoc_GetDataHere ! 1391: * --------------------- ! 1392: * ! 1393: * Render data from the document on a CALLER allocated STGMEDIUM. ! 1394: * This routine is called via IDataObject::GetDataHere. ! 1395: */ ! 1396: HRESULT ServerDoc_GetDataHere ( ! 1397: LPSERVERDOC lpServerDoc, ! 1398: LPFORMATETC lpformatetc, ! 1399: LPSTGMEDIUM lpMedium ! 1400: ) ! 1401: { ! 1402: LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; ! 1403: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 1404: LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; ! 1405: LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; ! 1406: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; ! 1407: HRESULT hrErr; ! 1408: SCODE sc; ! 1409: ! 1410: // OLE2NOTE: we must set out pointer parameters to NULL ! 1411: lpMedium->pUnkForRelease = NULL; ! 1412: ! 1413: /* our user document does not support any formats for GetDataHere. ! 1414: ** if the document is used for ! 1415: ** purposes of data transfer, then additional formats are offered. ! 1416: */ ! 1417: if (! lpOutlineDoc->m_fDataTransferDoc) { ! 1418: sc = DATA_E_FORMATETC; ! 1419: goto error; ! 1420: } ! 1421: ! 1422: if (lpformatetc->cfFormat == lpOleApp->m_cfEmbedSource) { ! 1423: hrErr = OleStdGetOleObjectData( ! 1424: (LPPERSISTSTORAGE)&lpServerDoc->m_PersistStorage, ! 1425: lpformatetc, ! 1426: lpMedium, ! 1427: FALSE /* fUseMemory -- (use file-base stg) */ ! 1428: ); ! 1429: if (hrErr != NOERROR) { ! 1430: sc = GetScode(hrErr); ! 1431: goto error; ! 1432: } ! 1433: OleDbgOut3("ServerDoc_GetDataHere: rendered CF_EMBEDSOURCE\r\n"); ! 1434: return NOERROR; ! 1435: ! 1436: } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) { ! 1437: if (lpOleDoc->m_fLinkSourceAvail) { ! 1438: LPMONIKER lpmk; ! 1439: ! 1440: lpmk = ServerDoc_GetSelFullMoniker( ! 1441: (LPSERVERDOC)lpOleDoc->m_lpSrcDocOfCopy, ! 1442: &lpServerDoc->m_lrSrcSelOfCopy, ! 1443: GETMONIKER_FORCEASSIGN ! 1444: ); ! 1445: if (lpmk) { ! 1446: hrErr = OleStdGetLinkSourceData( ! 1447: lpmk, ! 1448: (LPCLSID)&CLSID_APP, ! 1449: lpformatetc, ! 1450: lpMedium ! 1451: ); ! 1452: OleStdRelease((LPUNKNOWN)lpmk); ! 1453: if (hrErr != NOERROR) { ! 1454: sc = GetScode(hrErr); ! 1455: goto error; ! 1456: } ! 1457: ! 1458: OleDbgOut3( ! 1459: "ServerDoc_GetDataHere: rendered CF_LINKSOURCE\r\n"); ! 1460: return NOERROR; ! 1461: ! 1462: } else { ! 1463: sc = E_FAIL; ! 1464: goto error; ! 1465: } ! 1466: } else { ! 1467: sc = DATA_E_FORMATETC; ! 1468: goto error; ! 1469: } ! 1470: } else { ! 1471: ! 1472: /* Caller is requesting data to be returned in Caller allocated ! 1473: ** medium, but we do NOT support this. we only support ! 1474: ** global memory blocks that WE allocate for the caller. ! 1475: */ ! 1476: sc = DATA_E_FORMATETC; ! 1477: goto error; ! 1478: } ! 1479: ! 1480: return NOERROR; ! 1481: ! 1482: error: ! 1483: return ResultFromScode(sc); ! 1484: } ! 1485: ! 1486: ! 1487: /* ServerDoc_QueryGetData ! 1488: * ---------------------- ! 1489: * ! 1490: * Answer if a particular data format is supported via GetData/GetDataHere. ! 1491: * This routine is called via IDataObject::QueryGetData. ! 1492: */ ! 1493: ! 1494: HRESULT ServerDoc_QueryGetData (LPSERVERDOC lpServerDoc,LPFORMATETC lpformatetc) ! 1495: { ! 1496: LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; ! 1497: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpServerDoc; ! 1498: LPSERVERAPP lpServerApp = (LPSERVERAPP)g_lpApp; ! 1499: LPOLEAPP lpOleApp = (LPOLEAPP)lpServerApp; ! 1500: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpServerApp; ! 1501: ! 1502: /* Caller is querying if we support certain format but does not ! 1503: ** want any data actually returned. ! 1504: */ ! 1505: if (lpformatetc->cfFormat == lpOutlineApp->m_cfOutline || ! 1506: lpformatetc->cfFormat == CF_TEXT) { ! 1507: // we only support HGLOBAL ! 1508: return OleStdQueryFormatMedium(lpformatetc, TYMED_HGLOBAL); ! 1509: } else if (lpformatetc->cfFormat == CF_METAFILEPICT && ! 1510: (lpformatetc->dwAspect & ! 1511: (DVASPECT_CONTENT | DVASPECT_CONTENT | DVASPECT_DOCPRINT)) ) { ! 1512: return OleStdQueryFormatMedium(lpformatetc, TYMED_MFPICT); ! 1513: } ! 1514: ! 1515: /* the above are the only formats supports by a user document (ie. ! 1516: ** a non-data transfer doc). if the document is used for ! 1517: ** purposes of data transfer, then additional formats are offered. ! 1518: */ ! 1519: if (! lpOutlineDoc->m_fDataTransferDoc) ! 1520: return ResultFromScode(DATA_E_FORMATETC); ! 1521: ! 1522: if (lpformatetc->cfFormat == lpOleApp->m_cfEmbedSource) { ! 1523: return OleStdQueryOleObjectData(lpformatetc); ! 1524: ! 1525: } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource && ! 1526: lpOleDoc->m_fLinkSourceAvail) { ! 1527: return OleStdQueryLinkSourceData(lpformatetc); ! 1528: ! 1529: } else if (lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor) { ! 1530: return OleStdQueryObjectDescriptorData(lpformatetc); ! 1531: ! 1532: } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor && ! 1533: lpOleDoc->m_fLinkSourceAvail) { ! 1534: return OleStdQueryObjectDescriptorData(lpformatetc); ! 1535: } ! 1536: ! 1537: return ResultFromScode(DATA_E_FORMATETC); ! 1538: } ! 1539: ! 1540: ! 1541: /* ServerDoc_EnumFormatEtc ! 1542: * ----------------------- ! 1543: * ! 1544: * Return an enumerator which enumerates the data accepted/offered by ! 1545: * the document. ! 1546: * This routine is called via IDataObject::EnumFormatEtc. ! 1547: */ ! 1548: HRESULT ServerDoc_EnumFormatEtc( ! 1549: LPSERVERDOC lpServerDoc, ! 1550: DWORD dwDirection, ! 1551: LPENUMFORMATETC FAR* lplpenumFormatEtc ! 1552: ) ! 1553: { ! 1554: LPOLEDOC lpOleDoc = (LPOLEDOC)lpServerDoc; ! 1555: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 1556: int nActualFmts; ! 1557: SCODE sc = S_OK; ! 1558: ! 1559: /* OLE2NOTE: the enumeration of formats for a data transfer ! 1560: ** document is not a static list. the list of formats offered ! 1561: ** may or may not include CF_LINKSOURCE depending on whether a ! 1562: ** moniker is available for our document. thus we can NOT use ! 1563: ** the default OLE enumerator which enumerates the formats that ! 1564: ** are registered for our app in the registration database. ! 1565: */ ! 1566: if (dwDirection == DATADIR_GET) { ! 1567: nActualFmts = lpOleApp->m_nDocGetFmts; ! 1568: ! 1569: /* If the document does not have a Moniker, then exclude ! 1570: ** CF_LINKSOURCE and CF_LINKSRCDESCRIPTOR from the list of ! 1571: ** formats available. these formats are deliberately listed ! 1572: ** last in the array of possible "Get" formats. ! 1573: */ ! 1574: if (! lpOleDoc->m_fLinkSourceAvail) ! 1575: nActualFmts -= 2; ! 1576: ! 1577: *lplpenumFormatEtc = OleStdEnumFmtEtc_Create( ! 1578: nActualFmts, lpOleApp->m_arrDocGetFmts); ! 1579: if (*lplpenumFormatEtc == NULL) ! 1580: sc = E_OUTOFMEMORY; ! 1581: ! 1582: } else if (dwDirection == DATADIR_SET) { ! 1583: /* OLE2NOTE: a document that is used to transfer data ! 1584: ** (either via the clipboard or drag/drop does NOT ! 1585: ** accept SetData on ANY format! ! 1586: */ ! 1587: sc = E_NOTIMPL; ! 1588: goto error; ! 1589: } else { ! 1590: sc = E_INVALIDARG; ! 1591: goto error; ! 1592: } ! 1593: ! 1594: error: ! 1595: return ResultFromScode(sc); ! 1596: } ! 1597: ! 1598: ! 1599: /* ServerDoc_GetMetafilePictData ! 1600: * ----------------------------- ! 1601: * ! 1602: * Return a handle to an object's picture data in metafile format. ! 1603: * ! 1604: * ! 1605: * RETURNS: A handle to the object's data in metafile format. ! 1606: * ! 1607: */ ! 1608: HGLOBAL ServerDoc_GetMetafilePictData( ! 1609: LPSERVERDOC lpServerDoc, ! 1610: LPLINERANGE lplrSel ! 1611: ) ! 1612: { ! 1613: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 1614: LPOUTLINEDOC lpOutlineDoc=(LPOUTLINEDOC)lpServerDoc; ! 1615: LPLINELIST lpLL=(LPLINELIST)&lpOutlineDoc->m_LineList; ! 1616: LPLINE lpLine; ! 1617: LPMETAFILEPICT lppict = NULL; ! 1618: HGLOBAL hMFPict = NULL; ! 1619: HMETAFILE hMF = NULL; ! 1620: RECT rect; ! 1621: HDC hDC; ! 1622: int i; ! 1623: int nWidth; ! 1624: int nStart = (lplrSel ? lplrSel->m_nStartLine : 0); ! 1625: int nEnd =(lplrSel ? lplrSel->m_nEndLine : LineList_GetCount(lpLL)-1); ! 1626: int nLines = nEnd - nStart + 1; ! 1627: UINT fuAlign; ! 1628: POINT point; ! 1629: SIZE size; ! 1630: ! 1631: hDC = CreateMetaFile(NULL); ! 1632: ! 1633: rect.left = 0; ! 1634: rect.right = 0; ! 1635: rect.bottom = 0; ! 1636: ! 1637: if (nLines > 0) { ! 1638: // calculate the total height/width of LineList in HIMETRIC ! 1639: for(i = nStart; i <= nEnd; i++) { ! 1640: lpLine = LineList_GetLine(lpLL,i); ! 1641: nWidth = Line_GetTotalWidthInHimetric(lpLine); ! 1642: rect.right = max(rect.right, nWidth); ! 1643: rect.bottom -= Line_GetHeightInHimetric(lpLine); ! 1644: } ! 1645: ! 1646: ! 1647: SetMapMode(hDC, MM_ANISOTROPIC); ! 1648: ! 1649: SetWindowOrgEx(hDC, 0, 0, &point); ! 1650: SetWindowExtEx(hDC, rect.right, rect.bottom, &size); ! 1651: ! 1652: // Set the default font size, and font face name ! 1653: SelectObject(hDC, OutlineApp_GetActiveFont(lpOutlineApp)); ! 1654: ! 1655: FillRect(hDC, (LPRECT) &rect, GetStockObject(WHITE_BRUSH)); ! 1656: ! 1657: rect.bottom = 0; ! 1658: ! 1659: fuAlign = SetTextAlign(hDC, TA_LEFT | TA_TOP | TA_NOUPDATECP); ! 1660: ! 1661: /* While more lines print out the text */ ! 1662: for(i = nStart; i <= nEnd; i++) { ! 1663: lpLine = LineList_GetLine(lpLL,i); ! 1664: ! 1665: rect.top = rect.bottom; ! 1666: rect.bottom -= Line_GetHeightInHimetric(lpLine); ! 1667: ! 1668: /* Draw the line */ ! 1669: Line_Draw(lpLine, hDC, &rect); ! 1670: } ! 1671: ! 1672: SetTextAlign(hDC, fuAlign); ! 1673: } ! 1674: ! 1675: // Get handle to the metafile. ! 1676: if (!(hMF = CloseMetaFile (hDC))) ! 1677: return NULL; ! 1678: ! 1679: if (!(hMFPict = GlobalAlloc (GMEM_SHARE | GMEM_ZEROINIT, ! 1680: sizeof (METAFILEPICT)))) { ! 1681: DeleteMetaFile (hMF); ! 1682: return NULL; ! 1683: } ! 1684: ! 1685: if (!(lppict = (LPMETAFILEPICT)GlobalLock(hMFPict))) { ! 1686: DeleteMetaFile (hMF); ! 1687: GlobalFree (hMFPict); ! 1688: return NULL; ! 1689: } ! 1690: ! 1691: lppict->mm = MM_ANISOTROPIC; ! 1692: lppict->hMF = hMF; ! 1693: lppict->xExt = rect.right; ! 1694: lppict->yExt = - rect.bottom; // add minus sign to make it +ve ! 1695: GlobalUnlock (hMFPict); ! 1696: ! 1697: return hMFPict; ! 1698: } ! 1699: ! 1700: #endif // OLE_SERVER ! 1701: ! 1702: ! 1703: ! 1704: #if defined( OLE_CNTR ) ! 1705: ! 1706: /************************************************************************* ! 1707: ** ContainerDoc Supprt Functions Used by Container versions ! 1708: *************************************************************************/ ! 1709: ! 1710: ! 1711: /* Paste OLE Link from clipboard */ ! 1712: void ContainerDoc_PasteLinkCommand(LPCONTAINERDOC lpContainerDoc) ! 1713: { ! 1714: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 1715: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 1716: LPDATAOBJECT lpClipboardDataObj = NULL; ! 1717: BOOL fLink = TRUE; ! 1718: BOOL fLocalDataObj = FALSE; ! 1719: BOOL fDisplayAsIcon = FALSE; ! 1720: HCURSOR hPrevCursor; ! 1721: HGLOBAL hMem = NULL; ! 1722: HGLOBAL hMetaPict = NULL; ! 1723: STGMEDIUM medium; ! 1724: BOOL fStatus; ! 1725: HRESULT hrErr; ! 1726: ! 1727: hrErr = OleGetClipboard((LPDATAOBJECT FAR*)&lpClipboardDataObj); ! 1728: if (hrErr != NOERROR) ! 1729: return; // Clipboard seems to be empty or can't be accessed ! 1730: ! 1731: // this may take a while, put up hourglass cursor ! 1732: hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); ! 1733: ! 1734: /* check if the data on the clipboard is local to our application ! 1735: ** instance. ! 1736: */ ! 1737: if (lpOutlineApp->m_lpClipboardDoc) { ! 1738: LPOLEDOC lpOleDoc = (LPOLEDOC)lpOutlineApp->m_lpClipboardDoc; ! 1739: if (lpClipboardDataObj == (LPDATAOBJECT)&lpOleDoc->m_DataObject) ! 1740: fLocalDataObj = TRUE; ! 1741: } ! 1742: ! 1743: /* OLE2NOTE: we need to check what dwDrawAspect is being ! 1744: ** transfered. if the data is an object that is displayed as an ! 1745: ** icon in the source, then we want to keep it as an icon. the ! 1746: ** aspect the object is displayed in at the source is transfered ! 1747: ** via the CF_LINKSOURCEDESCRIPTOR format for a PasteLink ! 1748: ** operation. ! 1749: */ ! 1750: if (hMem = OleStdGetData( ! 1751: lpClipboardDataObj, ! 1752: lpOleApp->m_cfLinkSrcDescriptor, ! 1753: NULL, ! 1754: DVASPECT_CONTENT, ! 1755: (LPSTGMEDIUM)&medium)) { ! 1756: LPOBJECTDESCRIPTOR lpOD = GlobalLock(hMem); ! 1757: fDisplayAsIcon = (lpOD->dwDrawAspect == DVASPECT_ICON ? TRUE : FALSE); ! 1758: GlobalUnlock(hMem); ! 1759: ReleaseStgMedium((LPSTGMEDIUM)&medium); // equiv to GlobalFree ! 1760: ! 1761: if (fDisplayAsIcon) { ! 1762: hMetaPict = OleStdGetData( ! 1763: lpClipboardDataObj, ! 1764: CF_METAFILEPICT, ! 1765: NULL, ! 1766: DVASPECT_ICON, ! 1767: (LPSTGMEDIUM)&medium ! 1768: ); ! 1769: if (hMetaPict == NULL) ! 1770: fDisplayAsIcon = FALSE; // give up; failed to get icon MFP ! 1771: } ! 1772: } ! 1773: ! 1774: fStatus = ContainerDoc_PasteFormatFromData( ! 1775: lpContainerDoc, ! 1776: lpOleApp->m_cfLinkSource, ! 1777: lpClipboardDataObj, ! 1778: fLocalDataObj, ! 1779: fLink, ! 1780: fDisplayAsIcon, ! 1781: hMetaPict ! 1782: ); ! 1783: ! 1784: if (!fStatus) ! 1785: OutlineApp_ErrorMessage(g_lpApp, ErrMsgPasting); ! 1786: ! 1787: if (hMetaPict) ! 1788: ReleaseStgMedium((LPSTGMEDIUM)&medium); // properly free METAFILEPICT ! 1789: ! 1790: if (lpClipboardDataObj) ! 1791: OleStdRelease((LPUNKNOWN)lpClipboardDataObj); ! 1792: ! 1793: SetCursor(hPrevCursor); // restore original cursor ! 1794: } ! 1795: ! 1796: ! 1797: /* ContainerDoc_PasteFormatFromData ! 1798: ** -------------------------------- ! 1799: ** ! 1800: ** Paste a particular data format from a IDataObject*. The ! 1801: ** IDataObject* may come from the clipboard (GetClipboard) or from a ! 1802: ** drag/drop operation. ! 1803: ** ! 1804: ** Returns TRUE if data was successfully pasted. ! 1805: ** FALSE if data could not be pasted. ! 1806: */ ! 1807: BOOL ContainerDoc_PasteFormatFromData( ! 1808: LPCONTAINERDOC lpContainerDoc, ! 1809: CLIPFORMAT cfFormat, ! 1810: LPDATAOBJECT lpSrcDataObj, ! 1811: BOOL fLocalDataObj, ! 1812: BOOL fLink, ! 1813: BOOL fDisplayAsIcon, ! 1814: HGLOBAL hMetaPict ! 1815: ) ! 1816: { ! 1817: LPLINELIST lpLL = (LPLINELIST)&((LPOUTLINEDOC)lpContainerDoc)->m_LineList; ! 1818: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 1819: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 1820: LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; ! 1821: int nIndex; ! 1822: int nCount = 0; ! 1823: HGLOBAL hData; ! 1824: STGMEDIUM medium; ! 1825: FORMATETC formatetc; ! 1826: HRESULT hrErr; ! 1827: LINERANGE lrSel; ! 1828: ! 1829: if (LineList_GetCount(lpLL) == 0) ! 1830: nIndex = -1; // pasting to empty list ! 1831: else ! 1832: nIndex=LineList_GetFocusLineIndex(lpLL); ! 1833: ! 1834: if (fLink) { ! 1835: ! 1836: /* We should paste a Link to the data */ ! 1837: ! 1838: if (cfFormat != lpOleApp->m_cfLinkSource) ! 1839: return FALSE; // we only support OLE object type links ! 1840: ! 1841: nCount = ContainerDoc_PasteOleObject( ! 1842: lpContainerDoc, ! 1843: lpSrcDataObj, ! 1844: OLECREATEFROMDATA_LINK, ! 1845: cfFormat, ! 1846: nIndex, ! 1847: fDisplayAsIcon, ! 1848: hMetaPict ! 1849: ); ! 1850: return (nCount > 0 ? TRUE : FALSE); ! 1851: ! 1852: } else { ! 1853: ! 1854: if (cfFormat == lpContainerApp->m_cfCntrOutl) { ! 1855: if (fLocalDataObj) { ! 1856: ! 1857: /* CASE I: IDataObject* is local to our app ! 1858: ** ! 1859: ** if the source of the data is local to our ! 1860: ** application instance, then we can get direct ! 1861: ** access to the original OleDoc object that ! 1862: ** corresponds to the IDataObject* given. ! 1863: ** CF_CNTROUTL data is passed through a LPSTORAGE. ! 1864: ** if we call OleGetData asking for CF_CNTROUTL, we ! 1865: ** will be returned a copy of the existing open pStg ! 1866: ** of the original source document. we can NOT open ! 1867: ** streams and sub-storages again via this pStg ! 1868: ** since it is already open within our same ! 1869: ** application instance. we must copy the data from ! 1870: ** the original OleDoc source document. ! 1871: */ ! 1872: LPLINELIST lpSrcLL; ! 1873: LPOLEDOC lpLocalSrcDoc = ! 1874: ((struct CDocDataObjectImpl FAR*)lpSrcDataObj)->lpOleDoc; ! 1875: ! 1876: /* copy all lines from SrcDoc to DestDoc. */ ! 1877: lpSrcLL = &((LPOUTLINEDOC)lpLocalSrcDoc)->m_LineList; ! 1878: nCount = LineList_CopySelToDoc( ! 1879: lpSrcLL, ! 1880: NULL, ! 1881: (LPOUTLINEDOC)lpContainerDoc ! 1882: ); ! 1883: ! 1884: } else { ! 1885: ! 1886: /* CASE II: IDataObject* is NOT local to our app ! 1887: ** ! 1888: ** if the source of the data comes from another ! 1889: ** application instance. we can call GetDataHere to ! 1890: ** retrieve the CF_CNTROUTL data. CF_CNTROUTL data ! 1891: ** is passed through a LPSTORAGE. we MUST use ! 1892: ** IDataObject::GetDataHere. calling ! 1893: ** IDataObject::GetData does NOT work because OLE ! 1894: ** currently does NOT support remoting of a callee ! 1895: ** allocated root storage back to the caller. this ! 1896: ** hopefully will be supported in a future version. ! 1897: ** in order to call GetDataHere we must allocate an ! 1898: ** IStorage instance for the callee to write into. ! 1899: ** we will allocate an IStorage docfile that will ! 1900: ** delete-on-release. we could use either a ! 1901: ** memory-based storage or a file-based storage. ! 1902: */ ! 1903: LPSTORAGE lpTmpStg = OleStdCreateTempStorage( ! 1904: FALSE /*fUseMemory*/, ! 1905: STGM_READWRITE | STGM_TRANSACTED |STGM_SHARE_EXCLUSIVE ! 1906: ); ! 1907: if (! lpTmpStg) ! 1908: return FALSE; ! 1909: ! 1910: formatetc.cfFormat = cfFormat; ! 1911: formatetc.ptd = NULL; ! 1912: formatetc.dwAspect = DVASPECT_CONTENT; ! 1913: formatetc.tymed = TYMED_ISTORAGE; ! 1914: formatetc.lindex = -1; ! 1915: ! 1916: medium.tymed = TYMED_ISTORAGE; ! 1917: medium.u.pstg = lpTmpStg; ! 1918: medium.pUnkForRelease = NULL; ! 1919: ! 1920: OLEDBG_BEGIN2("IDataObject::GetDataHere called\r\n") ! 1921: hrErr = lpSrcDataObj->lpVtbl->GetDataHere( ! 1922: lpSrcDataObj, ! 1923: (LPFORMATETC)&formatetc, ! 1924: (LPSTGMEDIUM)&medium ! 1925: ); ! 1926: OLEDBG_END2 ! 1927: ! 1928: if (hrErr == NOERROR) { ! 1929: nCount = ContainerDoc_PasteCntrOutlData( ! 1930: lpContainerDoc, ! 1931: lpTmpStg, ! 1932: nIndex ! 1933: ); ! 1934: } ! 1935: OleStdVerifyRelease( ! 1936: (LPUNKNOWN)lpTmpStg, "Temp stg NOT released!\r\n"); ! 1937: return ((hrErr == NOERROR) ? TRUE : FALSE); ! 1938: } ! 1939: ! 1940: } else if (cfFormat == lpOutlineApp->m_cfOutline) { ! 1941: ! 1942: hData = OleStdGetData( ! 1943: lpSrcDataObj, ! 1944: lpOutlineApp->m_cfOutline, ! 1945: NULL, ! 1946: DVASPECT_CONTENT, ! 1947: (LPSTGMEDIUM)&medium ! 1948: ); ! 1949: nCount = OutlineDoc_PasteOutlineData( ! 1950: (LPOUTLINEDOC)lpContainerDoc, ! 1951: hData, ! 1952: nIndex ! 1953: ); ! 1954: // OLE2NOTE: we must free data handle by releasing the medium ! 1955: ReleaseStgMedium((LPSTGMEDIUM)&medium); ! 1956: ! 1957: } else if (cfFormat == lpOleApp->m_cfEmbedSource || ! 1958: cfFormat == lpOleApp->m_cfEmbeddedObject || ! 1959: cfFormat == lpOleApp->m_cfFileName) { ! 1960: /* OLE2NOTE: OleCreateFromData API creates an OLE object if ! 1961: ** CF_EMBEDDEDOBJECT, CF_EMBEDSOURCE, or CF_FILENAME are ! 1962: ** available from the source data object. the ! 1963: ** CF_FILENAME case arises when a file is copied to the ! 1964: ** clipboard from the FileManager. if the file has an ! 1965: ** associated class (see GetClassFile API), then an ! 1966: ** object of that class is created. otherwise an OLE 1.0 ! 1967: ** Packaged object is created. ! 1968: */ ! 1969: nCount = ContainerDoc_PasteOleObject( ! 1970: lpContainerDoc, ! 1971: lpSrcDataObj, ! 1972: OLECREATEFROMDATA_OBJECT, ! 1973: 0, /* N/A -- cfFormat */ ! 1974: nIndex, ! 1975: fDisplayAsIcon, ! 1976: hMetaPict ! 1977: ); ! 1978: return (nCount > 0 ? TRUE : FALSE); ! 1979: ! 1980: } else if (cfFormat == CF_METAFILEPICT ! 1981: || cfFormat == CF_DIB ! 1982: || cfFormat == CF_BITMAP) { ! 1983: ! 1984: /* OLE2NOTE: OleCreateStaticFromData API creates an static ! 1985: ** OLE object if CF_METAFILEPICT, CF_DIB, or CF_BITMAP is ! 1986: ** CF_EMBEDDEDOBJECT, CF_EMBEDSOURCE, or CF_FILENAME are ! 1987: ** available from the source data object. ! 1988: */ ! 1989: nCount = ContainerDoc_PasteOleObject( ! 1990: lpContainerDoc, ! 1991: lpSrcDataObj, ! 1992: OLECREATEFROMDATA_STATIC, ! 1993: cfFormat, ! 1994: nIndex, ! 1995: fDisplayAsIcon, ! 1996: hMetaPict ! 1997: ); ! 1998: return (nCount > 0 ? TRUE : FALSE); ! 1999: ! 2000: } else if(cfFormat == CF_TEXT) { ! 2001: ! 2002: hData = OleStdGetData( ! 2003: lpSrcDataObj, ! 2004: CF_TEXT, ! 2005: NULL, ! 2006: DVASPECT_CONTENT, ! 2007: (LPSTGMEDIUM)&medium ! 2008: ); ! 2009: nCount = OutlineDoc_PasteTextData( ! 2010: (LPOUTLINEDOC)lpContainerDoc, ! 2011: hData, ! 2012: nIndex ! 2013: ); ! 2014: // OLE2NOTE: we must free data handle by releasing the medium ! 2015: ReleaseStgMedium((LPSTGMEDIUM)&medium); ! 2016: ! 2017: } else { ! 2018: return FALSE; // no acceptable format available to paste ! 2019: } ! 2020: } ! 2021: ! 2022: lrSel.m_nStartLine = nIndex + nCount; ! 2023: lrSel.m_nEndLine = nIndex + 1; ! 2024: LineList_SetSel(lpLL, &lrSel); ! 2025: return TRUE; ! 2026: } ! 2027: ! 2028: ! 2029: /* ContainerDoc_PasteCntrOutlData ! 2030: * ------------------------------- ! 2031: * ! 2032: * Load the lines stored in a lpSrcStg (stored in CF_CNTROUTL format) ! 2033: * into the document. ! 2034: * ! 2035: * Return the number of items added ! 2036: */ ! 2037: int ContainerDoc_PasteCntrOutlData( ! 2038: LPCONTAINERDOC lpDestContainerDoc, ! 2039: LPSTORAGE lpSrcStg, ! 2040: int nStartIndex ! 2041: ) ! 2042: { ! 2043: int nCount; ! 2044: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 2045: LPOUTLINEDOC lpDestOutlineDoc = (LPOUTLINEDOC)lpDestContainerDoc; ! 2046: LPOUTLINEDOC lpSrcOutlineDoc; ! 2047: LPLINELIST lpSrcLL; ! 2048: ! 2049: // create a temp document that will be used to load the lpSrcStg data. ! 2050: lpSrcOutlineDoc = (LPOUTLINEDOC)OutlineApp_CreateDoc(lpOutlineApp, FALSE); ! 2051: if ( ! lpSrcOutlineDoc ) ! 2052: return 0; ! 2053: ! 2054: if (! OutlineDoc_LoadFromStg(lpSrcOutlineDoc, lpSrcStg)) ! 2055: goto error; ! 2056: ! 2057: /* copy all lines from the SrcDoc to the DestDoc. */ ! 2058: lpSrcLL = &lpSrcOutlineDoc->m_LineList; ! 2059: nCount = LineList_CopySelToDoc(lpSrcLL, NULL, lpDestOutlineDoc); ! 2060: ! 2061: if (lpSrcOutlineDoc) // destroy temporary document. ! 2062: OutlineDoc_Close(lpSrcOutlineDoc, OLECLOSE_NOSAVE); ! 2063: ! 2064: return nCount; ! 2065: ! 2066: error: ! 2067: if (lpSrcOutlineDoc) // destroy temporary document. ! 2068: OutlineDoc_Close(lpSrcOutlineDoc, OLECLOSE_NOSAVE); ! 2069: ! 2070: return 0; ! 2071: } ! 2072: ! 2073: ! 2074: /* ContainerDoc_QueryPasteFromData ! 2075: ** ------------------------------- ! 2076: ** ! 2077: ** Check if the IDataObject* offers data in a format that we can ! 2078: ** paste. The IDataObject* may come from the clipboard ! 2079: ** (GetClipboard) or from a drag/drop operation. ! 2080: ** In this function we look if one of the following formats is ! 2081: ** offered: ! 2082: ** CF_OUTLINE ! 2083: ** <OLE object -- CF_EMBEDSOURCE or CF_EMBEDDEDOBJECT> ! 2084: ** CF_TEXT ! 2085: ** ! 2086: ** NOTE: fLink is specified and CF_LINKSOURCE is available then TRUE ! 2087: ** is returned, else FALSE. ! 2088: ** ! 2089: ** Returns TRUE if paste can be performed ! 2090: ** FALSE if paste is not possible. ! 2091: */ ! 2092: BOOL ContainerDoc_QueryPasteFromData( ! 2093: LPCONTAINERDOC lpContainerDoc, ! 2094: LPDATAOBJECT lpSrcDataObj, ! 2095: BOOL fLink ! 2096: ) ! 2097: { ! 2098: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 2099: ! 2100: if (fLink) { ! 2101: /* check if we can paste a Link to the data */ ! 2102: if (OleQueryLinkFromData(lpSrcDataObj) != NOERROR) ! 2103: return FALSE; // linking is NOT possible ! 2104: } else { ! 2105: ! 2106: int nFmtEtc; ! 2107: ! 2108: nFmtEtc = OleStdGetPriorityClipboardFormat( ! 2109: lpSrcDataObj, ! 2110: lpOleApp->m_arrPasteEntries, ! 2111: lpOleApp->m_nPasteEntries ! 2112: ); ! 2113: ! 2114: if (nFmtEtc < 0) ! 2115: return FALSE; // there is no format we like ! 2116: } ! 2117: ! 2118: return TRUE; ! 2119: } ! 2120: ! 2121: ! 2122: /* ContainerDoc_PasteOleObject ! 2123: ** --------------------------- ! 2124: ** ! 2125: ** Embed or link an OLE object. the source of the data is a pointer ! 2126: ** to an IDataObject. normally this lpSrcDataObj comes from the ! 2127: ** clipboard after call OleGetClipboard. ! 2128: ** ! 2129: ** dwCreateType controls what type of object will created: ! 2130: ** OLECREATEFROMDATA_LINK -- OleCreateLinkFromData will be called ! 2131: ** OLECREATEFROMDATA_OBJECT -- OleCreateFromData will be called ! 2132: ** OLECREATEFROMDATA_STATIC -- OleCreateStaticFromData will be called ! 2133: ** cfFormat controls the type of static ! 2134: ** a CONTAINERLINE object is created to manage the OLE object. this ! 2135: ** CONTAINERLINE is added to the ContainerDoc after line nIndex. ! 2136: ** ! 2137: */ ! 2138: int ContainerDoc_PasteOleObject( ! 2139: LPCONTAINERDOC lpContainerDoc, ! 2140: LPDATAOBJECT lpSrcDataObj, ! 2141: DWORD dwCreateType, ! 2142: CLIPFORMAT cfFormat, ! 2143: int nIndex, ! 2144: BOOL fDisplayAsIcon, ! 2145: HGLOBAL hMetaPict ! 2146: ) ! 2147: { ! 2148: LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerDoc)->m_LineList; ! 2149: LPLINE lpLine = NULL; ! 2150: HDC hDC; ! 2151: int nTab = 0; ! 2152: char szStgName[CWCSTORAGENAME]; ! 2153: LPCONTAINERLINE lpContainerLine = NULL; ! 2154: ! 2155: ContainerDoc_GetNextStgName(lpContainerDoc, szStgName, sizeof(szStgName)); ! 2156: ! 2157: /* default the new line to have the same indent as previous line */ ! 2158: lpLine = LineList_GetLine(lpLL, nIndex); ! 2159: if (lpLine) ! 2160: nTab = Line_GetTabLevel(lpLine); ! 2161: ! 2162: hDC = LineList_GetDC(lpLL); ! 2163: ! 2164: lpContainerLine = ContainerLine_CreateFromData( ! 2165: hDC, ! 2166: nTab, ! 2167: lpContainerDoc, ! 2168: lpSrcDataObj, ! 2169: dwCreateType, ! 2170: cfFormat, ! 2171: fDisplayAsIcon, ! 2172: hMetaPict, ! 2173: szStgName ! 2174: ); ! 2175: LineList_ReleaseDC(lpLL, hDC); ! 2176: ! 2177: if (! lpContainerLine) ! 2178: goto error; ! 2179: ! 2180: /* add a ContainerLine object to the document's LineList. The ! 2181: ** ContainerLine manages the rectangle on the screen occupied by ! 2182: ** the OLE object. later when the app is updated to support ! 2183: ** extended layout, there could be more than one Line associated ! 2184: ** with the OLE object. ! 2185: */ ! 2186: ! 2187: LineList_AddLine(lpLL, (LPLINE)lpContainerLine, nIndex); ! 2188: ! 2189: // check to see if the object has any initial extents. ! 2190: ContainerLine_UpdateExtent(lpContainerLine, NULL); ! 2191: ! 2192: OutlineDoc_SetModified((LPOUTLINEDOC)lpContainerDoc, TRUE, TRUE, TRUE); ! 2193: ! 2194: return 1; // one line added to LineList ! 2195: ! 2196: error: ! 2197: // NOTE: if ContainerLine_CreateFromClip failed ! 2198: OutlineApp_ErrorMessage(g_lpApp, "Paste Object failed!"); ! 2199: return 0; // no lines added to line list ! 2200: } ! 2201: ! 2202: ! 2203: /* ContainerDoc_GetData ! 2204: * -------------------- ! 2205: * ! 2206: * Render data from the document on a CALLEE allocated STGMEDIUM. ! 2207: * This routine is called via IDataObject::GetData. ! 2208: */ ! 2209: HRESULT ContainerDoc_GetData ( ! 2210: LPCONTAINERDOC lpContainerDoc, ! 2211: LPFORMATETC lpformatetc, ! 2212: LPSTGMEDIUM lpMedium ! 2213: ) ! 2214: { ! 2215: LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; ! 2216: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; ! 2217: LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; ! 2218: LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp; ! 2219: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp; ! 2220: HRESULT hrErr; ! 2221: SCODE sc; ! 2222: ! 2223: // OLE2NOTE: we must set out pointer parameters to NULL ! 2224: lpMedium->pUnkForRelease = NULL; ! 2225: ! 2226: /* OLE2NOTE: we must set all out pointer parameters to NULL. */ ! 2227: lpMedium->tymed = TYMED_NULL; ! 2228: lpMedium->pUnkForRelease = NULL; // we transfer ownership to caller ! 2229: lpMedium->u.hGlobal = NULL; ! 2230: ! 2231: if (lpformatetc->cfFormat == lpContainerApp->m_cfCntrOutl) { ! 2232: ! 2233: /* OLE2NOTE: currently OLE does NOT support remoting a root ! 2234: ** level IStorage (either memory or file based) as an OUT ! 2235: ** parameter. thus, we can NOT support GetData for this ! 2236: ** TYMED_ISTORAGE based format. the caller MUST call GetDataHere. ! 2237: */ ! 2238: sc = DATA_E_FORMATETC; ! 2239: goto error; ! 2240: ! 2241: } else if (lpformatetc->cfFormat == lpOutlineApp->m_cfOutline) { ! 2242: // Verify caller asked for correct medium ! 2243: if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { ! 2244: sc = DATA_E_FORMATETC; ! 2245: goto error; ! 2246: } ! 2247: ! 2248: lpMedium->u.hGlobal = OutlineDoc_GetOutlineData(lpOutlineDoc, NULL); ! 2249: if (! lpMedium->u.hGlobal) { ! 2250: sc = E_OUTOFMEMORY; ! 2251: goto error; ! 2252: } ! 2253: ! 2254: lpMedium->tymed = TYMED_HGLOBAL; ! 2255: OleDbgOut3("ContainerDoc_GetData: rendered CF_OUTLINE\r\n"); ! 2256: return NOERROR; ! 2257: ! 2258: } else if (lpformatetc->cfFormat == CF_TEXT) { ! 2259: // Verify caller asked for correct medium ! 2260: if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { ! 2261: sc = DATA_E_FORMATETC; ! 2262: goto error; ! 2263: } ! 2264: ! 2265: lpMedium->u.hGlobal = OutlineDoc_GetTextData ( ! 2266: (LPOUTLINEDOC)lpContainerDoc, ! 2267: NULL ! 2268: ); ! 2269: if (! lpMedium->u.hGlobal) { ! 2270: sc = E_OUTOFMEMORY; ! 2271: goto error; ! 2272: } ! 2273: ! 2274: lpMedium->tymed = TYMED_HGLOBAL; ! 2275: OleDbgOut3("ContainerDoc_GetData: rendered CF_TEXT\r\n"); ! 2276: return NOERROR; ! 2277: ! 2278: } else if ( lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor || ! 2279: (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor && ! 2280: lpOleDoc->m_fLinkSourceAvail) ) { ! 2281: // Verify caller asked for correct medium ! 2282: if (!(lpformatetc->tymed & TYMED_HGLOBAL)) { ! 2283: sc = DATA_E_FORMATETC; ! 2284: goto error; ! 2285: } ! 2286: ! 2287: lpMedium->u.hGlobal = OleDoc_GetObjectDescriptorData ( ! 2288: (LPOLEDOC)lpContainerDoc, ! 2289: NULL ! 2290: ); ! 2291: if (! lpMedium->u.hGlobal) { ! 2292: sc = E_OUTOFMEMORY; ! 2293: goto error; ! 2294: } ! 2295: ! 2296: lpMedium->tymed = TYMED_HGLOBAL; ! 2297: #if defined( _DEBUG ) ! 2298: if (lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor) ! 2299: OleDbgOut3( ! 2300: "ContainerDoc_GetData: rendered CF_OBJECTDESCRIPTOR\r\n"); ! 2301: else ! 2302: OleDbgOut3( ! 2303: "ContainerDoc_GetData: rendered CF_LINKSRCDESCRIPTOR\r\n"); ! 2304: #endif ! 2305: return NOERROR; ! 2306: ! 2307: } else if (lpContainerDoc->m_fEmbeddedObjectAvail) { ! 2308: ! 2309: /* OLE2NOTE: if this document contains a single OLE object ! 2310: ** (ie. cfEmbeddedObject data format is available), then ! 2311: ** the formats offered via our IDataObject must include ! 2312: ** the formats available from the OLE object itself. ! 2313: ** thus, we delegate this call to the IDataObject* of the ! 2314: ** OLE object. ! 2315: */ ! 2316: ! 2317: if (lpformatetc->cfFormat == lpOleApp->m_cfEmbeddedObject) { ! 2318: LPPERSISTSTORAGE lpPersistStg = ! 2319: (LPPERSISTSTORAGE)ContainerDoc_GetSingleOleObject( ! 2320: lpContainerDoc, ! 2321: &IID_IPersistStorage, ! 2322: NULL ! 2323: ); ! 2324: ! 2325: if (! lpPersistStg) ! 2326: return ResultFromScode(DATA_E_FORMATETC); ! 2327: ! 2328: /* render CF_EMBEDDEDOBJECT by asking the storage to save ! 2329: ** into the pStg of the caller. ! 2330: */ ! 2331: ! 2332: hrErr = OleStdGetOleObjectData( ! 2333: lpPersistStg, ! 2334: lpformatetc, ! 2335: lpMedium, ! 2336: FALSE /* fUseMemory -- (use file-base stg) */ ! 2337: ); ! 2338: OleStdRelease((LPUNKNOWN)lpPersistStg); ! 2339: if (hrErr != NOERROR) { ! 2340: sc = GetScode(hrErr); ! 2341: goto error; ! 2342: } ! 2343: OleDbgOut3( ! 2344: "ContainerDoc_GetData: rendered CF_EMBEDDEDOBJECT\r\n"); ! 2345: return hrErr; ! 2346: ! 2347: } else if (lpformatetc->cfFormat == CF_METAFILEPICT) { ! 2348: ! 2349: /* OLE2NOTE: as a container which draws objects, when a single ! 2350: ** OLE object is copied, we can give the Metafile picture of ! 2351: ** the object. we will offer this picture when asked either ! 2352: ** for the actual drawing aspect that we are displaying for ! 2353: ** the object or for DVASPECT_DOCPRINT (if asked to render ! 2354: ** it to a printer) ! 2355: */ ! 2356: LPCONTAINERLINE lpContainerLine; ! 2357: LPOLEOBJECT lpOleObj; ! 2358: ! 2359: // Verify caller asked for correct medium ! 2360: if (!(lpformatetc->tymed & TYMED_MFPICT)) { ! 2361: sc = DATA_E_FORMATETC; ! 2362: goto error; ! 2363: } ! 2364: ! 2365: lpOleObj = (LPOLEOBJECT)ContainerDoc_GetSingleOleObject( ! 2366: lpContainerDoc, ! 2367: &IID_IOleObject, ! 2368: (LPCONTAINERLINE FAR*)&lpContainerLine ! 2369: ); ! 2370: ! 2371: if (! lpOleObj) { ! 2372: sc = E_OUTOFMEMORY; // could not load object ! 2373: goto error; ! 2374: } ! 2375: if (lpformatetc->dwAspect & ! 2376: (lpContainerLine->m_dwDrawAspect | DVASPECT_DOCPRINT)) { ! 2377: /* render CF_METAFILEPICT by drawing the object into ! 2378: ** a metafile DC ! 2379: */ ! 2380: lpMedium->u.hGlobal = OleStdGetMetafilePictFromOleObject( ! 2381: lpOleObj, lpContainerLine->m_dwDrawAspect); ! 2382: OleStdRelease((LPUNKNOWN)lpOleObj); ! 2383: if (! lpMedium->u.hGlobal) { ! 2384: sc = E_OUTOFMEMORY; ! 2385: goto error; ! 2386: } ! 2387: ! 2388: lpMedium->tymed = TYMED_MFPICT; ! 2389: OleDbgOut3( ! 2390: "ContainerDoc_GetData: rendered CF_METAFILEPICT\r\n"); ! 2391: return NOERROR; ! 2392: } else { ! 2393: // improper aspect requested ! 2394: OleStdRelease((LPUNKNOWN)lpOleObj); ! 2395: return ResultFromScode(DATA_E_FORMATETC); ! 2396: } ! 2397: ! 2398: } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) { ! 2399: if (lpOleDoc->m_fLinkSourceAvail) { ! 2400: LPMONIKER lpmk; ! 2401: ! 2402: lpmk = ContainerLine_GetFullMoniker( ! 2403: lpContainerDoc->m_lpSrcContainerLine, ! 2404: GETMONIKER_FORCEASSIGN ! 2405: ); ! 2406: if (lpmk) { ! 2407: hrErr = OleStdGetLinkSourceData( ! 2408: lpmk, ! 2409: &lpContainerDoc->m_clsidOleObjCopied, ! 2410: lpformatetc, ! 2411: lpMedium ! 2412: ); ! 2413: OleStdRelease((LPUNKNOWN)lpmk); ! 2414: if (hrErr != NOERROR) { ! 2415: sc = GetScode(hrErr); ! 2416: goto error; ! 2417: } ! 2418: OleDbgOut3( ! 2419: "ContainerDoc_GetData: rendered CF_LINKSOURCE\r\n"); ! 2420: return hrErr; ! 2421: } else { ! 2422: sc = DATA_E_FORMATETC; ! 2423: goto error; ! 2424: } ! 2425: } else { ! 2426: sc = DATA_E_FORMATETC; ! 2427: goto error; ! 2428: } ! 2429: ! 2430: } ! 2431: #if defined( OPTIONAL_ADVANCED_DATA_TRANSFER ) ! 2432: /* OLE2NOTE: optionally, a container that wants to have a ! 2433: ** potentially richer data transfer, can enumerate the data ! 2434: ** formats from the OLE object's cache and offer them too. if ! 2435: ** the object has a special handler, then it might be able to ! 2436: ** render additional data formats. in this case, the ! 2437: ** container must delegate the GetData call to the object if ! 2438: ** it does not directly support the format. ! 2439: ** ! 2440: ** CNTROUTL does NOT enumerate the cache; it implements the ! 2441: ** simpler strategy of offering a static list of formats. ! 2442: ** thus the delegation is NOT required. ! 2443: */ ! 2444: else { ! 2445: ! 2446: /* OLE2NOTE: we delegate this call to the IDataObject* of the ! 2447: ** OLE object. ! 2448: */ ! 2449: LPDATAOBJECT lpDataObj; ! 2450: ! 2451: lpDataObj = (LPDATAOBJECT)ContainerDoc_GetSingleOleObject( ! 2452: lpContainerDoc, ! 2453: &IID_IDataObject, ! 2454: NULL ! 2455: ); ! 2456: ! 2457: if (! lpDataObj) { ! 2458: sc = DATA_E_FORMATETC; ! 2459: goto error; ! 2460: } ! 2461: ! 2462: OLEDBG_BEGIN2("ContainerDoc_GetData: delegate to OLE obj\r\n") ! 2463: hrErr=lpDataObj->lpVtbl->GetData(lpDataObj,lpformatetc,lpMedium); ! 2464: OLEDBG_END2 ! 2465: ! 2466: OleStdRelease((LPUNKNOWN)lpDataObj); ! 2467: return hrErr; ! 2468: } ! 2469: #endif // ! OPTIONAL_ADVANCED_DATA_TRANSFER ! 2470: ! 2471: } ! 2472: ! 2473: // if we get here then we do NOT support the requested format ! 2474: sc = DATA_E_FORMATETC; ! 2475: ! 2476: error: ! 2477: return ResultFromScode(sc); ! 2478: } ! 2479: ! 2480: ! 2481: /* ContainerDoc_GetDataHere ! 2482: * ------------------------ ! 2483: * ! 2484: * Render data from the document on a CALLER allocated STGMEDIUM. ! 2485: * This routine is called via IDataObject::GetDataHere. ! 2486: */ ! 2487: HRESULT ContainerDoc_GetDataHere ( ! 2488: LPCONTAINERDOC lpContainerDoc, ! 2489: LPFORMATETC lpformatetc, ! 2490: LPSTGMEDIUM lpMedium ! 2491: ) ! 2492: { ! 2493: LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; ! 2494: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; ! 2495: LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; ! 2496: LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp; ! 2497: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp; ! 2498: HRESULT hrErr; ! 2499: ! 2500: // OLE2NOTE: we must set out pointer parameters to NULL ! 2501: lpMedium->pUnkForRelease = NULL; ! 2502: ! 2503: // we only support IStorage medium ! 2504: if (lpformatetc->cfFormat == lpContainerApp->m_cfCntrOutl) { ! 2505: if (!(lpformatetc->tymed & TYMED_ISTORAGE)) ! 2506: return ResultFromScode(DATA_E_FORMATETC); ! 2507: ! 2508: if (lpMedium->tymed == TYMED_ISTORAGE) { ! 2509: /* Caller has allocated the storage. we must copy all of our ! 2510: ** data into his storage. ! 2511: */ ! 2512: ! 2513: /* OLE2NOTE: we must be sure to write our class ID into our ! 2514: ** storage. this information is used by OLE to determine the ! 2515: ** class of the data stored in our storage. ! 2516: */ ! 2517: if((hrErr=WriteClassStg(lpMedium->u.pstg,&CLSID_APP)) != NOERROR) ! 2518: return hrErr; ! 2519: ! 2520: OutlineDoc_SaveSelToStg( ! 2521: (LPOUTLINEDOC)lpContainerDoc, ! 2522: NULL, /* entire doc */ ! 2523: lpContainerApp->m_cfCntrOutl, ! 2524: lpMedium->u.pstg, ! 2525: FALSE ! 2526: ); ! 2527: OleStdCommitStorage(lpMedium->u.pstg); ! 2528: ! 2529: OleDbgOut3("ContainerDoc_GetDataHere: rendered CF_CNTROUTL\r\n"); ! 2530: return NOERROR; ! 2531: } else { ! 2532: // we only support IStorage medium ! 2533: return ResultFromScode(DATA_E_FORMATETC); ! 2534: } ! 2535: ! 2536: } else if (lpContainerDoc->m_fEmbeddedObjectAvail) { ! 2537: ! 2538: /* OLE2NOTE: if this document contains a single OLE object ! 2539: ** (ie. cfEmbeddedObject data format is available), then ! 2540: ** the formats offered via our IDataObject must include ! 2541: ** CF_EMBEDDEDOBJECT and the formats available from the OLE ! 2542: ** object itself. ! 2543: */ ! 2544: ! 2545: if (lpformatetc->cfFormat == lpOleApp->m_cfEmbeddedObject) { ! 2546: LPPERSISTSTORAGE lpPersistStg = ! 2547: (LPPERSISTSTORAGE)ContainerDoc_GetSingleOleObject( ! 2548: lpContainerDoc, ! 2549: &IID_IPersistStorage, ! 2550: NULL ! 2551: ); ! 2552: ! 2553: if (! lpPersistStg) { ! 2554: return ResultFromScode(E_OUTOFMEMORY); ! 2555: } ! 2556: /* render CF_EMBEDDEDOBJECT by asking the storage to save ! 2557: ** into the pStg of the caller. ! 2558: */ ! 2559: ! 2560: hrErr = OleStdGetOleObjectData( ! 2561: lpPersistStg, ! 2562: lpformatetc, ! 2563: lpMedium, ! 2564: FALSE /* fUseMemory -- (use file-base stg) */ ! 2565: ); ! 2566: OleStdRelease((LPUNKNOWN)lpPersistStg); ! 2567: if (hrErr != NOERROR) { ! 2568: return hrErr; ! 2569: } ! 2570: OleDbgOut3( ! 2571: "ContainerDoc_GetDataHere: rendered CF_EMBEDDEDOBJECT\r\n"); ! 2572: return hrErr; ! 2573: ! 2574: } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource) { ! 2575: if (lpOleDoc->m_fLinkSourceAvail) { ! 2576: LPMONIKER lpmk; ! 2577: ! 2578: lpmk = ContainerLine_GetFullMoniker( ! 2579: lpContainerDoc->m_lpSrcContainerLine, ! 2580: GETMONIKER_FORCEASSIGN ! 2581: ); ! 2582: if (lpmk) { ! 2583: hrErr = OleStdGetLinkSourceData( ! 2584: lpmk, ! 2585: &lpContainerDoc->m_clsidOleObjCopied, ! 2586: lpformatetc, ! 2587: lpMedium ! 2588: ); ! 2589: OleStdRelease((LPUNKNOWN)lpmk); ! 2590: OleDbgOut3( ! 2591: "ContainerDoc_GetDataHere: rendered CF_LINKSOURCE\r\n"); ! 2592: return hrErr; ! 2593: } else { ! 2594: return ResultFromScode(E_FAIL); ! 2595: } ! 2596: } else { ! 2597: return ResultFromScode(DATA_E_FORMATETC); ! 2598: } ! 2599: ! 2600: } ! 2601: #if defined( OPTIONAL_ADVANCED_DATA_TRANSFER ) ! 2602: /* OLE2NOTE: optionally, a container that wants to have a ! 2603: ** potentially richer data transfer, can enumerate the data ! 2604: ** formats from the OLE object's cache and offer them too. if ! 2605: ** the object has a special handler, then it might be able to ! 2606: ** render additional data formats. in this case, the ! 2607: ** container must delegate the GetData call to the object if ! 2608: ** it does not directly support the format. ! 2609: ** ! 2610: ** CNTROUTL does NOT enumerate the cache; it implements the ! 2611: ** simpler strategy of offering a static list of formats. ! 2612: ** thus the delegation is NOT required. ! 2613: */ ! 2614: else { ! 2615: ! 2616: /* OLE2NOTE: we delegate this call to the IDataObject* of the ! 2617: ** OLE object. ! 2618: */ ! 2619: LPDATAOBJECT lpDataObj; ! 2620: ! 2621: lpDataObj = (LPDATAOBJECT)ContainerDoc_GetSingleOleObject( ! 2622: lpContainerDoc, ! 2623: &IID_IDataObject, ! 2624: NULL ! 2625: ); ! 2626: ! 2627: if (! lpDataObj) ! 2628: return ResultFromScode(DATA_E_FORMATETC); ! 2629: ! 2630: OLEDBG_BEGIN2("ContainerDoc_GetDataHere: delegate to OLE obj\r\n") ! 2631: hrErr = lpDataObj->lpVtbl->GetDataHere( ! 2632: lpDataObj, ! 2633: lpformatetc, ! 2634: lpMedium ! 2635: ); ! 2636: OLEDBG_END2 ! 2637: ! 2638: OleStdRelease((LPUNKNOWN)lpDataObj); ! 2639: return hrErr; ! 2640: } ! 2641: #endif // OPTIONAL_ADVANCED_DATA_TRANSFER ! 2642: } else { ! 2643: return ResultFromScode(DATA_E_FORMATETC); ! 2644: } ! 2645: } ! 2646: ! 2647: ! 2648: /* ContainerDoc_QueryGetData ! 2649: * ------------------------- ! 2650: * ! 2651: * Answer if a particular data format is supported via GetData/GetDataHere. ! 2652: * This routine is called via IDataObject::QueryGetData. ! 2653: */ ! 2654: HRESULT ContainerDoc_QueryGetData ( ! 2655: LPCONTAINERDOC lpContainerDoc, ! 2656: LPFORMATETC lpformatetc ! 2657: ) ! 2658: { ! 2659: LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; ! 2660: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; ! 2661: LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; ! 2662: LPOLEAPP lpOleApp = (LPOLEAPP)lpContainerApp; ! 2663: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)lpContainerApp; ! 2664: LPDATAOBJECT lpDataObj = NULL; ! 2665: LPCONTAINERLINE lpContainerLine = NULL; ! 2666: SCODE sc; ! 2667: HRESULT hrErr; ! 2668: ! 2669: if (lpContainerDoc->m_fEmbeddedObjectAvail) { ! 2670: lpDataObj = (LPDATAOBJECT)ContainerDoc_GetSingleOleObject( ! 2671: lpContainerDoc, ! 2672: &IID_IDataObject, ! 2673: (LPCONTAINERLINE FAR*)&lpContainerLine ! 2674: ); ! 2675: } ! 2676: ! 2677: /* Caller is querying if we support certain format but does not ! 2678: ** want any data actually returned. ! 2679: */ ! 2680: if (lpformatetc->cfFormat == lpContainerApp->m_cfCntrOutl) { ! 2681: // we only support ISTORAGE medium ! 2682: sc = GetScode( OleStdQueryFormatMedium(lpformatetc, TYMED_ISTORAGE) ); ! 2683: ! 2684: } else if (lpformatetc->cfFormat == lpOleApp->m_cfEmbeddedObject && ! 2685: lpContainerDoc->m_fEmbeddedObjectAvail ) { ! 2686: sc = GetScode( OleStdQueryOleObjectData(lpformatetc) ); ! 2687: ! 2688: } else if (lpformatetc->cfFormat == lpOleApp->m_cfLinkSource && ! 2689: lpOleDoc->m_fLinkSourceAvail) { ! 2690: sc = GetScode( OleStdQueryLinkSourceData(lpformatetc) ); ! 2691: ! 2692: } else if((lpformatetc->cfFormat == (lpOutlineApp)->m_cfOutline || ! 2693: lpformatetc->cfFormat == CF_TEXT) ) { ! 2694: // we only support HGLOBAL medium ! 2695: sc = GetScode( OleStdQueryFormatMedium(lpformatetc, TYMED_HGLOBAL) ); ! 2696: ! 2697: } else if ( lpformatetc->cfFormat == lpOleApp->m_cfObjectDescriptor || ! 2698: (lpformatetc->cfFormat == lpOleApp->m_cfLinkSrcDescriptor && ! 2699: lpOleDoc->m_fLinkSourceAvail) ) { ! 2700: sc = GetScode( OleStdQueryObjectDescriptorData(lpformatetc) ); ! 2701: ! 2702: } else if (lpformatetc->cfFormat == CF_METAFILEPICT && ! 2703: lpContainerDoc->m_fEmbeddedObjectAvail && lpContainerLine && ! 2704: (lpformatetc->dwAspect & ! 2705: (lpContainerLine->m_dwDrawAspect | DVASPECT_DOCPRINT))) { ! 2706: ! 2707: /* OLE2NOTE: as a container which draws objects, when a single ! 2708: ** OLE object is copied, we can give the Metafile picture of ! 2709: ** the object. we will offer this picture when asked either ! 2710: ** for the actual drawing aspect that we are displaying for ! 2711: ** the object or for DVASPECT_DOCPRINT (if asked to render ! 2712: ** it to a printer) ! 2713: */ ! 2714: // we only support MFPICT medium ! 2715: sc = GetScode( OleStdQueryFormatMedium(lpformatetc, TYMED_MFPICT) ); ! 2716: ! 2717: } else if (lpDataObj) { ! 2718: ! 2719: /* OLE2NOTE: if this document contains a single OLE object ! 2720: ** (ie. cfEmbeddedObject data format is available), then ! 2721: ** the formats offered via our IDataObject must include ! 2722: ** the formats available from the OLE object itself. ! 2723: ** thus we delegate this call to the IDataObject* of the ! 2724: ** OLE object. ! 2725: */ ! 2726: OLEDBG_BEGIN2("ContainerDoc_QueryGetData: delegate to OLE obj\r\n") ! 2727: hrErr = lpDataObj->lpVtbl->QueryGetData(lpDataObj, lpformatetc); ! 2728: OLEDBG_END2 ! 2729: ! 2730: sc = GetScode(hrErr); ! 2731: ! 2732: } else { ! 2733: sc = DATA_E_FORMATETC; ! 2734: } ! 2735: ! 2736: if (lpDataObj) ! 2737: OleStdRelease((LPUNKNOWN)lpDataObj); ! 2738: return ResultFromScode(sc); ! 2739: } ! 2740: ! 2741: ! 2742: ! 2743: /* ContainerDoc_SetData ! 2744: * -------------------- ! 2745: * ! 2746: * Set (modify) data of the document. ! 2747: * This routine is called via IDataObject::SetData. ! 2748: */ ! 2749: HRESULT ContainerDoc_SetData ( ! 2750: LPCONTAINERDOC lpContainerDoc, ! 2751: LPFORMATETC lpformatetc, ! 2752: LPSTGMEDIUM lpmedium, ! 2753: BOOL fRelease ! 2754: ) ! 2755: { ! 2756: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; ! 2757: LPOUTLINEAPP lpOutlineApp = (LPOUTLINEAPP)g_lpApp; ! 2758: ! 2759: if (lpformatetc->cfFormat == lpOutlineApp->m_cfOutline) ! 2760: OutlineDoc_PasteOutlineData(lpOutlineDoc,lpmedium->u.hGlobal,-1); ! 2761: else if (lpformatetc->cfFormat == CF_TEXT) ! 2762: OutlineDoc_PasteTextData(lpOutlineDoc,lpmedium->u.hGlobal,-1); ! 2763: else ! 2764: return ResultFromScode(DATA_E_FORMATETC); ! 2765: ! 2766: return NOERROR; ! 2767: } ! 2768: ! 2769: ! 2770: /* ContainerDoc_EnumFormatEtc ! 2771: * -------------------------- ! 2772: * ! 2773: * Return an enumerator which enumerates the data accepted/offered by ! 2774: * the document. ! 2775: * This routine is called via IDataObject::SetData. ! 2776: */ ! 2777: HRESULT ContainerDoc_EnumFormatEtc( ! 2778: LPCONTAINERDOC lpContainerDoc, ! 2779: DWORD dwDirection, ! 2780: LPENUMFORMATETC FAR* lplpenumFormatEtc ! 2781: ) ! 2782: { ! 2783: LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; ! 2784: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerDoc; ! 2785: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 2786: LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)lpOleApp; ! 2787: int nActualFmts; ! 2788: int i; ! 2789: SCODE sc = S_OK; ! 2790: ! 2791: /* the Container-Only version of Outline does NOT offer ! 2792: ** IDataObject interface from its User documents. ! 2793: */ ! 2794: if (! lpOutlineDoc->m_fDataTransferDoc) ! 2795: return ResultFromScode(E_FAIL); ! 2796: ! 2797: if (dwDirection == DATADIR_GET) { ! 2798: if (lpContainerDoc->m_fEmbeddedObjectAvail) { ! 2799: ! 2800: /* OLE2NOTE: if this document contains a single OLE object ! 2801: ** (ie. cfEmbeddedObject data format is available), then ! 2802: ** the formats offered via our enumerator must include ! 2803: ** the formats available from the OLE object itself. we ! 2804: ** have previously set up a special array of FORMATETC's ! 2805: ** in OutlineDoc_CreateDataTransferDoc routine which includes ! 2806: ** the combination of data we offer directly and data ! 2807: ** offered by the OLE object. ! 2808: */ ! 2809: ! 2810: /* If the document does not have a Moniker, then exclude ! 2811: ** CF_LINKSOURCE CF_LINKSRCDESCRIPTOR from the list of ! 2812: ** formats available. these formats are deliberately ! 2813: ** listed last in the array of possible "Get" formats. ! 2814: */ ! 2815: nActualFmts = lpContainerApp->m_nSingleObjGetFmts; ! 2816: if (! lpOleDoc->m_fLinkSourceAvail) ! 2817: nActualFmts -= 2; ! 2818: ! 2819: // set correct dwDrawAspect for METAFILEPICT of object copied ! 2820: for (i = 0; i < nActualFmts; i++) { ! 2821: if (lpContainerApp->m_arrSingleObjGetFmts[i].cfFormat == ! 2822: CF_METAFILEPICT) { ! 2823: lpContainerApp->m_arrSingleObjGetFmts[i].dwAspect = ! 2824: lpContainerDoc->m_dwAspectOleObjCopied; ! 2825: break; // DONE ! 2826: } ! 2827: } ! 2828: *lplpenumFormatEtc = OleStdEnumFmtEtc_Create( ! 2829: nActualFmts, lpContainerApp->m_arrSingleObjGetFmts); ! 2830: if (*lplpenumFormatEtc == NULL) ! 2831: sc = E_OUTOFMEMORY; ! 2832: ! 2833: } else { ! 2834: ! 2835: /* This document does NOT offer cfEmbeddedObject, ! 2836: ** therefore we can simply enumerate the ! 2837: ** static list of formats that we handle directly. ! 2838: */ ! 2839: *lplpenumFormatEtc = OleStdEnumFmtEtc_Create( ! 2840: lpOleApp->m_nDocGetFmts, lpOleApp->m_arrDocGetFmts); ! 2841: if (*lplpenumFormatEtc == NULL) ! 2842: sc = E_OUTOFMEMORY; ! 2843: } ! 2844: } else if (dwDirection == DATADIR_SET) { ! 2845: /* OLE2NOTE: a document that is used to transfer data ! 2846: ** (either via the clipboard or drag/drop does NOT ! 2847: ** accept SetData on ANY format! ! 2848: */ ! 2849: sc = E_NOTIMPL; ! 2850: ! 2851: } else { ! 2852: sc = E_NOTIMPL; ! 2853: } ! 2854: ! 2855: return ResultFromScode(sc); ! 2856: } ! 2857: ! 2858: ! 2859: #if defined( OPTIONAL_ADVANCED_DATA_TRANSFER ) ! 2860: /* OLE2NOTE: optionally, a container that wants to have a ! 2861: ** potentially richer data transfer, can enumerate the data ! 2862: ** formats from the OLE object's cache and offer them too. if ! 2863: ** the object has a special handler, then it might be able to ! 2864: ** render additional data formats. ! 2865: ** ! 2866: ** CNTROUTL does NOT enumerate the cache; it implements the simpler ! 2867: ** strategy of offering a static list of formats. the following ! 2868: ** function is included in order to illustrates how enumerating the ! 2869: ** cache could be done. CNTROUTL does NOT call this function. ! 2870: ** ! 2871: */ ! 2872: ! 2873: /* ContainerDoc_SetupDocGetFmts ! 2874: ** ---------------------------- ! 2875: ** Setup the combined list of formats that this data transfer ! 2876: ** ContainerDoc which contains a single OLE object should offer. ! 2877: ** ! 2878: ** OLE2NOTE: The list of formats that should be offered when a ! 2879: ** single OLE object is being transfered include the following: ! 2880: ** * any formats the container app wants to give ! 2881: ** * CF_EMBEDDEDOBJECT ! 2882: ** * CF_METAFILEPICT ! 2883: ** * any formats that the OLE object's cache can offer directly ! 2884: ** ! 2885: ** We will offer the following formats in the order given: ! 2886: ** 1. CF_CNTROUTL ! 2887: ** 2. CF_EMBEDDEDOBJECT ! 2888: ** 3. CF_OBJECTDESCRIPTOR ! 2889: ** 4. CF_METAFILEPICT ! 2890: ** 5. <data formats from OLE object's cache> ! 2891: ** 6. CF_OUTLINE ! 2892: ** 7. CF_TEXT ! 2893: ** 8. CF_LINKSOURCE ! 2894: ** 9. CF_LINKSRCDESCRIPTOR ! 2895: */ ! 2896: BOOL ContainerDoc_SetupDocGetFmts( ! 2897: LPCONTAINERDOC lpContainerDoc, ! 2898: LPCONTAINERLINE lpContainerLine ! 2899: ) ! 2900: { ! 2901: LPOLEDOC lpOleDoc = (LPOLEDOC)lpContainerDoc; ! 2902: LPOLEAPP lpOleApp = (LPOLEAPP)g_lpApp; ! 2903: LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; ! 2904: LPOLECACHE lpOleCache; ! 2905: HRESULT hrErr; ! 2906: STATDATA StatData; ! 2907: LPENUMSTATDATA lpEnumStatData = NULL; ! 2908: LPFORMATETC lparrDocGetFmts = NULL; ! 2909: UINT nOleObjFmts = 0; ! 2910: UINT nTotalFmts; ! 2911: UINT i; ! 2912: UINT iFmt; ! 2913: ! 2914: lpOleCache = (LPOLECACHE)OleStdQueryInterface( ! 2915: (LPUNKNOWN)lpContainerLine->m_lpOleObj, ! 2916: &IID_IOleCache ! 2917: ); ! 2918: if (lpOleCache) { ! 2919: OLEDBG_BEGIN2("IOleCache::EnumCache called\r\n") ! 2920: hrErr = lpOleCache->lpVtbl->EnumCache( ! 2921: lpOleCache, ! 2922: (LPENUMSTATDATA FAR*)&lpEnumStatData ! 2923: ); ! 2924: OLEDBG_END2 ! 2925: } ! 2926: ! 2927: if (lpEnumStatData) { ! 2928: /* Cache enumerator is available. count the number of ! 2929: ** formats that the OLE object's cache offers. ! 2930: */ ! 2931: while(lpEnumStatData->lpVtbl->Next( ! 2932: lpEnumStatData, ! 2933: 1, ! 2934: (LPSTATDATA)&StatData, ! 2935: NULL) == NOERROR) { ! 2936: nOleObjFmts++; ! 2937: // OLE2NOTE: we MUST free the TargetDevice ! 2938: OleStdFree(StatData.formatetc.ptd); ! 2939: } ! 2940: lpEnumStatData->lpVtbl->Reset(lpEnumStatData); // reset for next loop ! 2941: } ! 2942: ! 2943: /* OLE2NOTE: the maximum total number of formats that our IDataObject ! 2944: ** could offer equals the sum of the following: ! 2945: ** n offered by the OLE object's cache ! 2946: ** + n normally offered by our app ! 2947: ** + 1 CF_EMBEDDEDOBJECT ! 2948: ** + 1 CF_METAFILEPICT ! 2949: ** + 1 CF_LINKSOURCE ! 2950: ** + 1 CF_LINKSRCDESCRIPTOR ! 2951: ** the actual number of formats that we can offer could be less ! 2952: ** than this total if there is any clash between the formats ! 2953: ** that we offer directly and those offered by the cache. if ! 2954: ** there is a clash, the container's rendering overrides that of ! 2955: ** the object. eg.: as a container transfering an OLE object we ! 2956: ** should directly offer CF_METAFILEPICT to guarantee that this ! 2957: ** format is always available. thus, if the cache offers ! 2958: ** CF_METAFILEPICT then it is skipped. ! 2959: */ ! 2960: nTotalFmts = nOleObjFmts + lpOleApp->m_nDocGetFmts + 4; ! 2961: lparrDocGetFmts = (LPFORMATETC)New (nTotalFmts * sizeof(FORMATETC)); ! 2962: ! 2963: if (! OleDbgVerifySz(lparrDocGetFmts != NULL, ! 2964: "Error allocating arrDocGetFmts")) ! 2965: return FALSE; ! 2966: ! 2967: for (i = 0, iFmt = 0; i < lpOleApp->m_nDocGetFmts; i++) { ! 2968: _fmemcpy((LPFORMATETC)&lparrDocGetFmts[iFmt++], ! 2969: (LPFORMATETC)&lpOleApp->m_arrDocGetFmts[i], ! 2970: sizeof(FORMATETC) ! 2971: ); ! 2972: if (lpOleApp->m_arrDocGetFmts[i].cfFormat == ! 2973: lpContainerApp->m_cfCntrOutl) { ! 2974: /* insert CF_EMBEDDEDOBJECT, CF_METAFILEPICT, and formats ! 2975: ** available from the OLE object's cache following ! 2976: ** CF_CNTROUTL. ! 2977: */ ! 2978: lparrDocGetFmts[iFmt].cfFormat = lpOleApp->m_cfEmbeddedObject; ! 2979: lparrDocGetFmts[iFmt].ptd = NULL; ! 2980: lparrDocGetFmts[iFmt].dwAspect = DVASPECT_CONTENT; ! 2981: lparrDocGetFmts[iFmt].tymed = TYMED_ISTORAGE; ! 2982: lparrDocGetFmts[iFmt].lindex = -1; ! 2983: iFmt++; ! 2984: lparrDocGetFmts[iFmt].cfFormat = CF_METAFILEPICT; ! 2985: lparrDocGetFmts[iFmt].ptd = NULL; ! 2986: lparrDocGetFmts[iFmt].dwAspect = lpContainerLine->m_dwDrawAspect; ! 2987: lparrDocGetFmts[iFmt].tymed = TYMED_MFPICT; ! 2988: lparrDocGetFmts[iFmt].lindex = -1; ! 2989: iFmt++; ! 2990: ! 2991: if (lpEnumStatData) { ! 2992: /* Cache enumerator is available. enumerate all of ! 2993: ** the formats that the OLE object's cache offers. ! 2994: */ ! 2995: while(lpEnumStatData->lpVtbl->Next( ! 2996: lpEnumStatData, ! 2997: 1, ! 2998: (LPSTATDATA)&StatData, ! 2999: NULL) == NOERROR) { ! 3000: /* check if the format clashes with one of our fmts */ ! 3001: if (StatData.formatetc.cfFormat != CF_METAFILEPICT ! 3002: && ! OleStdIsDuplicateFormat( ! 3003: (LPFORMATETC)&StatData.formatetc, ! 3004: lpOleApp->m_arrDocGetFmts, ! 3005: lpOleApp->m_nDocGetFmts)) { ! 3006: OleStdCopyFormatEtc( ! 3007: &(lparrDocGetFmts[iFmt]),&StatData.formatetc); ! 3008: iFmt++; ! 3009: } ! 3010: // OLE2NOTE: we MUST free the TargetDevice ! 3011: OleStdFree(StatData.formatetc.ptd); ! 3012: } ! 3013: } ! 3014: } ! 3015: } ! 3016: ! 3017: if (lpOleCache) ! 3018: OleStdRelease((LPUNKNOWN)lpOleCache); ! 3019: ! 3020: /* append CF_LINKSOURCE format */ ! 3021: lparrDocGetFmts[iFmt].cfFormat = lpOleApp->m_cfLinkSource; ! 3022: lparrDocGetFmts[iFmt].ptd = NULL; ! 3023: lparrDocGetFmts[iFmt].dwAspect = DVASPECT_CONTENT; ! 3024: lparrDocGetFmts[iFmt].tymed = TYMED_ISTREAM; ! 3025: lparrDocGetFmts[iFmt].lindex = -1; ! 3026: iFmt++; ! 3027: ! 3028: /* append CF_LINKSRCDESCRIPTOR format */ ! 3029: lparrDocGetFmts[iFmt].cfFormat = lpOleApp->m_cfLinkSrcDescriptor; ! 3030: lparrDocGetFmts[iFmt].ptd = NULL; ! 3031: lparrDocGetFmts[iFmt].dwAspect = DVASPECT_CONTENT; ! 3032: lparrDocGetFmts[iFmt].tymed = TYMED_HGLOBAL; ! 3033: lparrDocGetFmts[iFmt].lindex = -1; ! 3034: iFmt++; ! 3035: ! 3036: lpContainerDoc->m_lparrDocGetFmts = lparrDocGetFmts; ! 3037: lpContainerDoc->m_nDocGetFmts = iFmt; ! 3038: ! 3039: if (lpEnumStatData) ! 3040: OleStdVerifyRelease( ! 3041: (LPUNKNOWN)lpEnumStatData, ! 3042: "Cache enumerator not released properly" ! 3043: ); ! 3044: ! 3045: return TRUE; ! 3046: } ! 3047: #endif // OPTIONAL_ADVANCED_DATA_TRANSFER ! 3048: ! 3049: #endif // OLE_CNTR
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.