|
|
1.1 ! root 1: /************************************************************************* ! 2: ** ! 3: ** OLE 2 Container Sample Code ! 4: ** ! 5: ** cntrline.c ! 6: ** ! 7: ** This file contains ContainerLine methods. ! 8: ** ! 9: ** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved ! 10: ** ! 11: *************************************************************************/ ! 12: ! 13: #include "outline.h" ! 14: ! 15: OLEDBGDATA ! 16: ! 17: ! 18: ! 19: extern LPOUTLINEAPP g_lpApp; ! 20: extern IUnknownVtbl g_CntrLine_UnknownVtbl; ! 21: extern IOleClientSiteVtbl g_CntrLine_OleClientSiteVtbl; ! 22: extern IAdviseSinkVtbl g_CntrLine_AdviseSinkVtbl; ! 23: ! 24: #if defined( INPLACE_CNTR ) ! 25: extern IOleInPlaceSiteVtbl g_CntrLine_OleInPlaceSiteVtbl; ! 26: extern BOOL g_fInsideOutContainer; ! 27: #endif // INPLACE_CNTR ! 28: ! 29: // REVIEW: should use string resource for messages ! 30: char ErrMsgDoVerb[] = "OLE object action failed!"; ! 31: ! 32: ! 33: /* prototype for static functions */ ! 34: static void InvertDiffRect(LPRECT lprcPix, LPRECT lprcObj, HDC hDC); ! 35: ! 36: ! 37: /************************************************************************* ! 38: ** ContainerLine ! 39: ** This object represents the location within the container where ! 40: ** the embedded/linked object lives. It exposes interfaces to the ! 41: ** object that allow the object to get information about its ! 42: ** embedding site and to announce notifications of important events ! 43: ** (changed, closed, saved) ! 44: ** ! 45: ** The ContainerLine exposes the following interfaces: ! 46: ** IOleClientSite ! 47: ** IAdviseSink ! 48: *************************************************************************/ ! 49: ! 50: ! 51: ! 52: /* ContainerLine_Init ! 53: ** ------------------ ! 54: ** Initialize fields in a newly constructed ContainerLine line object. ! 55: ** NOTE: ref cnt of ContainerLine initialized to 0 ! 56: */ ! 57: void ContainerLine_Init(LPCONTAINERLINE lpContainerLine, int nTab, HDC hDC) ! 58: { ! 59: Line_Init((LPLINE)lpContainerLine, nTab, hDC); // init base class fields ! 60: ! 61: ((LPLINE)lpContainerLine)->m_lineType = CONTAINERLINETYPE; ! 62: ((LPLINE)lpContainerLine)->m_nWidthInHimetric = DEFOBJWIDTH; ! 63: ((LPLINE)lpContainerLine)->m_nHeightInHimetric = DEFOBJHEIGHT; ! 64: lpContainerLine->m_cRef = 0; ! 65: lpContainerLine->m_szStgName[0] = '\0'; ! 66: lpContainerLine->m_fObjWinOpen = FALSE; ! 67: lpContainerLine->m_fMonikerAssigned = FALSE; ! 68: lpContainerLine->m_dwDrawAspect = DVASPECT_CONTENT; ! 69: ! 70: /* when we initially create the ContainerLine we do not know the ! 71: ** extents of the object. force the extents to be updated the ! 72: ** first time the line is drawn. ! 73: */ ! 74: lpContainerLine->m_fDoGetExtent = TRUE; ! 75: lpContainerLine->m_sizeInHimetric.cx = -1; ! 76: lpContainerLine->m_sizeInHimetric.cy = -1; ! 77: ! 78: lpContainerLine->m_lpStg = NULL; ! 79: lpContainerLine->m_lpOleObj = NULL; ! 80: lpContainerLine->m_lpViewObj = NULL; ! 81: lpContainerLine->m_lpPersistStg = NULL; ! 82: lpContainerLine->m_lpDoc = NULL; ! 83: lpContainerLine->m_fIsLink = FALSE; ! 84: lpContainerLine->m_fLinkUnavailable = FALSE; ! 85: lpContainerLine->m_lpszShortType = NULL; ! 86: ! 87: #if defined( INPLACE_CNTR ) ! 88: lpContainerLine->m_fIpActive = FALSE; ! 89: lpContainerLine->m_fUIActive = FALSE; ! 90: lpContainerLine->m_fIpVisible = FALSE; ! 91: lpContainerLine->m_lpOleIPObj = NULL; ! 92: lpContainerLine->m_fInsideOutObj = FALSE; ! 93: lpContainerLine->m_fIpChangesUndoable = FALSE; ! 94: lpContainerLine->m_fIpServerRunning = FALSE; ! 95: #endif // INPLACE_CNTR ! 96: ! 97: INIT_INTERFACEIMPL( ! 98: &lpContainerLine->m_Unknown, ! 99: &g_CntrLine_UnknownVtbl, ! 100: lpContainerLine ! 101: ); ! 102: ! 103: INIT_INTERFACEIMPL( ! 104: &lpContainerLine->m_OleClientSite, ! 105: &g_CntrLine_OleClientSiteVtbl, ! 106: lpContainerLine ! 107: ); ! 108: ! 109: INIT_INTERFACEIMPL( ! 110: &lpContainerLine->m_AdviseSink, ! 111: &g_CntrLine_AdviseSinkVtbl, ! 112: lpContainerLine ! 113: ); ! 114: ! 115: #if defined( INPLACE_CNTR ) ! 116: INIT_INTERFACEIMPL( ! 117: &lpContainerLine->m_OleInPlaceSite, ! 118: &g_CntrLine_OleInPlaceSiteVtbl, ! 119: lpContainerLine ! 120: ); ! 121: #endif // INPLACE_CNTR ! 122: } ! 123: ! 124: ! 125: /* Create an ContainerLine object and return the pointer */ ! 126: LPCONTAINERLINE ContainerLine_Create( ! 127: DWORD dwOleCreateType, ! 128: HDC hDC, ! 129: UINT nTab, ! 130: LPCONTAINERDOC lpContainerDoc, ! 131: LPCLSID lpclsid, ! 132: LPSTR lpszFileName, ! 133: BOOL fDisplayAsIcon, ! 134: HGLOBAL hMetaPict, ! 135: LPSTR lpszStgName ! 136: ) ! 137: { ! 138: LPCONTAINERLINE lpContainerLine = NULL; ! 139: LPOLEOBJECT lpObj = NULL; ! 140: LPSTORAGE lpDocStg = ContainerDoc_GetStg(lpContainerDoc); ! 141: DWORD dwDrawAspect = ! 142: (fDisplayAsIcon ? DVASPECT_ICON : DVASPECT_CONTENT); ! 143: DWORD dwOleRenderOpt = ! 144: (fDisplayAsIcon ? OLERENDER_NONE : OLERENDER_DRAW); ! 145: HRESULT hrErr; ! 146: ! 147: OLEDBG_BEGIN3("ContainerLine_Create\r\n") ! 148: ! 149: if (! OleDbgVerifySz(lpDocStg != NULL, "Doc storage is NULL")) ! 150: goto error; ! 151: ! 152: lpContainerLine=(LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); ! 153: if (lpContainerLine == NULL) { ! 154: OleDbgAssertSz( ! 155: lpContainerLine!=NULL, "Error allocating ContainerLine"); ! 156: goto error; ! 157: } ! 158: ! 159: ContainerLine_Init(lpContainerLine, nTab, hDC); ! 160: ! 161: /* OLE2NOTE: In order to have a stable ContainerLine object we must ! 162: ** AddRef the object's refcnt. this will be later released when ! 163: ** the ContainerLine is deleted. ! 164: */ ! 165: ContainerLine_AddRef(lpContainerLine); ! 166: ! 167: lstrcpy(lpContainerLine->m_szStgName, lpszStgName); ! 168: lpContainerLine->m_lpDoc = lpContainerDoc; ! 169: ! 170: /* Create a new storage for the object inside the doc's storage */ ! 171: lpContainerLine->m_lpStg = OleStdCreateChildStorage(lpDocStg,lpszStgName); ! 172: if (! OleDbgVerifySz(lpContainerLine->m_lpStg != NULL, ! 173: "Error creating child stg")) ! 174: goto error; ! 175: ! 176: lpContainerLine->m_fIsLink = FALSE; ! 177: ! 178: switch (dwOleCreateType) { ! 179: ! 180: case IOF_SELECTCREATENEW: ! 181: ! 182: OLEDBG_BEGIN2("OleCreate called\r\n") ! 183: hrErr = OleCreate ( ! 184: lpclsid, ! 185: &IID_IOleObject, ! 186: dwOleRenderOpt, ! 187: NULL, ! 188: (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, ! 189: lpContainerLine->m_lpStg, ! 190: (LPVOID FAR*)&lpContainerLine->m_lpOleObj ! 191: ); ! 192: OLEDBG_END2 ! 193: ! 194: #if defined( INPLACE_CNTR ) ! 195: /* OLE2NOTE: an inside-out container should check if ! 196: ** the object is an inside-out and prefers to be ! 197: ** activated when visible type of object. if not the ! 198: ** object should not be allowed to keep its window ! 199: ** up after it gets UIDeactivated. ! 200: */ ! 201: if (g_fInsideOutContainer && ! 202: lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT) { ! 203: DWORD mstat; ! 204: OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") ! 205: lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( ! 206: lpContainerLine->m_lpOleObj, ! 207: DVASPECT_CONTENT, ! 208: (DWORD FAR*)&mstat ! 209: ); ! 210: OLEDBG_END2 ! 211: ! 212: lpContainerLine->m_fInsideOutObj = (BOOL) ! 213: (mstat & ! 214: (OLEMISC_INSIDEOUT|OLEMISC_ACTIVATEWHENVISIBLE)); ! 215: } ! 216: #endif // INPLACE_CNTR ! 217: ! 218: break; ! 219: ! 220: case IOF_SELECTCREATEFROMFILE: ! 221: ! 222: OLEDBG_BEGIN2("OleCreateFromFile called\r\n") ! 223: ! 224: hrErr = OleCreateFromFile ( ! 225: &CLSID_NULL, ! 226: lpszFileName, ! 227: &IID_IOleObject, ! 228: dwOleRenderOpt, ! 229: NULL, ! 230: (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, ! 231: lpContainerLine->m_lpStg, ! 232: (LPVOID FAR*)&lpContainerLine->m_lpOleObj ! 233: ); ! 234: ! 235: OLEDBG_END2 ! 236: break; ! 237: ! 238: case IOF_CHECKLINK: ! 239: ! 240: OLEDBG_BEGIN2("OleCreateLinkToFile called\r\n") ! 241: ! 242: hrErr = OleCreateLinkToFile ( ! 243: lpszFileName, ! 244: &IID_IOleObject, ! 245: dwOleRenderOpt, ! 246: NULL, ! 247: (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, ! 248: lpContainerLine->m_lpStg, ! 249: (LPVOID FAR*)&lpContainerLine->m_lpOleObj ! 250: ); ! 251: ! 252: OLEDBG_END2 ! 253: lpContainerLine->m_fIsLink = TRUE; ! 254: break; ! 255: } ! 256: ! 257: if (hrErr != NOERROR) { ! 258: OutlineApp_ErrorMessage(g_lpApp, "Could not create object!"); ! 259: goto error; ! 260: } ! 261: ! 262: /* Setup the Advises (OLE notifications) that we are interested ! 263: ** in receiving. ! 264: */ ! 265: OleStdSetupAdvises( ! 266: lpContainerLine->m_lpOleObj, ! 267: dwDrawAspect, ! 268: (LPSTR)APPNAME, ! 269: ((LPOUTLINEDOC)lpContainerDoc)->m_lpszDocTitle, ! 270: (LPADVISESINK)&lpContainerLine->m_AdviseSink ! 271: ); ! 272: ! 273: if (fDisplayAsIcon) { ! 274: BOOL fMustUpdate; ! 275: ! 276: /* user has requested to display icon aspect instead of content ! 277: ** aspect. ! 278: ** NOTE: we do not have to delete the previous aspect cache ! 279: ** because one did not get set up. ! 280: */ ! 281: OleStdSwitchDisplayAspect( ! 282: lpContainerLine->m_lpOleObj, ! 283: &lpContainerLine->m_dwDrawAspect, ! 284: dwDrawAspect, ! 285: hMetaPict, ! 286: FALSE, /* fDeleteOldAspect */ ! 287: TRUE, /* fSetupViewAdvise */ ! 288: (LPADVISESINK)&lpContainerLine->m_AdviseSink, ! 289: (BOOL FAR*)&fMustUpdate // this can be ignored; update ! 290: // for switch to icon not req'd ! 291: ); ! 292: } ! 293: OLEDBG_END3 ! 294: return lpContainerLine; ! 295: ! 296: error: ! 297: // Destroy partially created OLE object ! 298: if (lpContainerLine) ! 299: ContainerLine_Delete(lpContainerLine); ! 300: OLEDBG_END3 ! 301: return NULL; ! 302: } ! 303: ! 304: ! 305: LPCONTAINERLINE ContainerLine_CreateFromData( ! 306: HDC hDC, ! 307: UINT nTab, ! 308: LPCONTAINERDOC lpContainerDoc, ! 309: LPDATAOBJECT lpSrcDataObj, ! 310: DWORD dwCreateType, ! 311: CLIPFORMAT cfFormat, ! 312: BOOL fDisplayAsIcon, ! 313: HGLOBAL hMetaPict, ! 314: LPSTR lpszStgName ! 315: ) ! 316: { ! 317: HGLOBAL hData = NULL; ! 318: LPCONTAINERLINE lpContainerLine = NULL; ! 319: LPOLEOBJECT lpObj = NULL; ! 320: LPSTORAGE lpDocStg = ContainerDoc_GetStg(lpContainerDoc); ! 321: DWORD dwDrawAspect = ! 322: (fDisplayAsIcon ? DVASPECT_ICON : DVASPECT_CONTENT); ! 323: DWORD dwOleRenderOpt = ! 324: (fDisplayAsIcon ? OLERENDER_NONE : OLERENDER_DRAW); ! 325: FORMATETC renderFmtEtc; ! 326: LPFORMATETC lpRenderFmtEtc = NULL; ! 327: HRESULT hrErr; ! 328: LPUNKNOWN lpUnk = NULL; ! 329: ! 330: OLEDBG_BEGIN3("ContainerLine_CreateFromData\r\n") ! 331: ! 332: if (dwCreateType == OLECREATEFROMDATA_STATIC && cfFormat != 0) { ! 333: // a particular type of static object should be created ! 334: ! 335: dwOleRenderOpt = OLERENDER_FORMAT; ! 336: lpRenderFmtEtc = (LPFORMATETC)&renderFmtEtc; ! 337: ! 338: if (cfFormat == CF_METAFILEPICT) ! 339: SETDEFAULTFORMATETC(renderFmtEtc, cfFormat, TYMED_MFPICT); ! 340: else if (cfFormat == CF_BITMAP) ! 341: SETDEFAULTFORMATETC(renderFmtEtc, cfFormat, TYMED_GDI); ! 342: else ! 343: SETDEFAULTFORMATETC(renderFmtEtc, cfFormat, TYMED_HGLOBAL); ! 344: } else if (fDisplayAsIcon) { ! 345: dwOleRenderOpt = OLERENDER_NONE; ! 346: ! 347: } else { ! 348: dwOleRenderOpt = OLERENDER_DRAW; ! 349: } ! 350: ! 351: if (! OleDbgVerifySz(lpDocStg != NULL, "Doc storage is NULL")) ! 352: goto error; ! 353: ! 354: lpContainerLine=(LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); ! 355: if (lpContainerLine == NULL) { ! 356: OleDbgAssertSz( ! 357: lpContainerLine!=NULL, "Error allocating ContainerLine"); ! 358: goto error; ! 359: } ! 360: ! 361: ContainerLine_Init(lpContainerLine, nTab, hDC); ! 362: ! 363: /* OLE2NOTE: In order to have a stable ContainerLine object we must ! 364: ** AddRef the object's refcnt. this will be later released when ! 365: ** the ContainerLine is deleted. ! 366: */ ! 367: ContainerLine_AddRef(lpContainerLine); ! 368: ! 369: lstrcpy(lpContainerLine->m_szStgName, lpszStgName); ! 370: lpContainerLine->m_lpDoc = lpContainerDoc; ! 371: ! 372: /* Create a new storage for the object inside the doc's storage */ ! 373: lpContainerLine->m_lpStg = OleStdCreateChildStorage(lpDocStg,lpszStgName); ! 374: if (! OleDbgVerifySz(lpContainerLine->m_lpStg != NULL, ! 375: "Error creating child stg")) ! 376: goto error; ! 377: ! 378: switch (dwCreateType) { ! 379: ! 380: case OLECREATEFROMDATA_LINK: ! 381: ! 382: OLEDBG_BEGIN2("OleCreateLinkFromData called\r\n") ! 383: hrErr = OleCreateLinkFromData ( ! 384: lpSrcDataObj, ! 385: &IID_IOleObject, ! 386: dwOleRenderOpt, ! 387: lpRenderFmtEtc, ! 388: (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, ! 389: lpContainerLine->m_lpStg, ! 390: (LPVOID FAR*)&lpContainerLine->m_lpOleObj ! 391: ); ! 392: OLEDBG_END2 ! 393: ! 394: if (hrErr != NOERROR) { ! 395: OleDbgOutHResult("OleCreateLinkFromData returned", hrErr); ! 396: } ! 397: ! 398: lpContainerLine->m_fIsLink = TRUE; ! 399: break; ! 400: ! 401: case OLECREATEFROMDATA_OBJECT: ! 402: ! 403: OLEDBG_BEGIN2("OleCreateFromData called\r\n") ! 404: hrErr = OleCreateFromData ( ! 405: lpSrcDataObj, ! 406: &IID_IOleObject, ! 407: dwOleRenderOpt, ! 408: lpRenderFmtEtc, ! 409: (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, ! 410: lpContainerLine->m_lpStg, ! 411: (LPVOID FAR*)&lpContainerLine->m_lpOleObj ! 412: ); ! 413: OLEDBG_END2 ! 414: ! 415: if (hrErr != NOERROR) { ! 416: OleDbgOutHResult("OleCreateFromData returned", hrErr); ! 417: } ! 418: ! 419: lpUnk=ContainerLine_GetOleObject(lpContainerLine,&IID_IOleLink); ! 420: if (lpUnk) { ! 421: OleStdRelease(lpUnk); ! 422: lpContainerLine->m_fIsLink = TRUE; ! 423: } ! 424: else { ! 425: lpContainerLine->m_fIsLink = FALSE; ! 426: ! 427: #if defined( INPLACE_CNTR ) ! 428: /* OLE2NOTE: an inside-out container should check if ! 429: ** the object is an inside-out and prefers to be ! 430: ** activated when visible type of object. if not the ! 431: ** object should not be allowed to keep its window ! 432: ** up after it gets UIDeactivated. ! 433: */ ! 434: if (g_fInsideOutContainer && ! 435: lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT) { ! 436: DWORD mstat; ! 437: OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") ! 438: lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( ! 439: lpContainerLine->m_lpOleObj, ! 440: DVASPECT_CONTENT, ! 441: (DWORD FAR*)&mstat ! 442: ); ! 443: OLEDBG_END2 ! 444: ! 445: lpContainerLine->m_fInsideOutObj = (BOOL) ! 446: (mstat & ! 447: (OLEMISC_INSIDEOUT|OLEMISC_ACTIVATEWHENVISIBLE)); ! 448: } ! 449: #endif // INPLACE_CNTR ! 450: ! 451: } ! 452: break; ! 453: ! 454: case OLECREATEFROMDATA_STATIC: ! 455: ! 456: OLEDBG_BEGIN2("OleCreateStaticFromData called\r\n") ! 457: hrErr = OleCreateStaticFromData ( ! 458: lpSrcDataObj, ! 459: &IID_IOleObject, ! 460: dwOleRenderOpt, ! 461: lpRenderFmtEtc, ! 462: (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, ! 463: lpContainerLine->m_lpStg, ! 464: (LPVOID FAR*)&lpContainerLine->m_lpOleObj ! 465: ); ! 466: OLEDBG_END2 ! 467: ! 468: if (hrErr != NOERROR) { ! 469: OleDbgOutHResult("OleCreateStaticFromData returned", hrErr); ! 470: } ! 471: ! 472: lpContainerLine->m_fIsLink = FALSE; ! 473: break; ! 474: } ! 475: ! 476: if (hrErr != NOERROR) { ! 477: OutlineApp_ErrorMessage(g_lpApp, "Could not create object!"); ! 478: goto error; ! 479: } ! 480: ! 481: /* Setup the Advises (OLE notifications) that we are interested ! 482: ** in receiving. ! 483: */ ! 484: OleStdSetupAdvises( ! 485: lpContainerLine->m_lpOleObj, ! 486: dwDrawAspect, ! 487: (LPSTR)APPNAME, ! 488: ((LPOUTLINEDOC)lpContainerDoc)->m_lpszDocTitle, ! 489: (LPADVISESINK)&lpContainerLine->m_AdviseSink ! 490: ); ! 491: ! 492: if (fDisplayAsIcon) { ! 493: BOOL fMustUpdate; ! 494: ! 495: /* user has requested to display icon aspect instead of content ! 496: ** aspect. ! 497: ** NOTE: we do not have to delete the previous aspect cache ! 498: ** because one did not get set up. ! 499: */ ! 500: OleStdSwitchDisplayAspect( ! 501: lpContainerLine->m_lpOleObj, ! 502: &lpContainerLine->m_dwDrawAspect, ! 503: dwDrawAspect, ! 504: hMetaPict, ! 505: FALSE, /* fDeleteOldAspect */ ! 506: TRUE, /* fSetupViewAdvise */ ! 507: (LPADVISESINK)&lpContainerLine->m_AdviseSink, ! 508: (BOOL FAR*)&fMustUpdate // this can be ignored; update ! 509: // for switch to icon not req'd ! 510: ); ! 511: } ! 512: ! 513: OLEDBG_END3 ! 514: return lpContainerLine; ! 515: ! 516: error: ! 517: // Destroy partially created OLE object ! 518: if (lpContainerLine) ! 519: ContainerLine_Delete(lpContainerLine); ! 520: OLEDBG_END3 ! 521: return NULL; ! 522: } ! 523: ! 524: ! 525: /* ContainerLine_AddRef ! 526: ** -------------------- ! 527: ** ! 528: ** increment the ref count of the line object. ! 529: ** ! 530: ** Returns the new ref count on the object ! 531: */ ! 532: ULONG ContainerLine_AddRef(LPCONTAINERLINE lpContainerLine) ! 533: { ! 534: ++lpContainerLine->m_cRef; ! 535: ! 536: OleDbgOutRefCnt4( ! 537: "ContainerLine_AddRef: cRef++\r\n", ! 538: lpContainerLine, ! 539: lpContainerLine->m_cRef ! 540: ); ! 541: ! 542: return lpContainerLine->m_cRef; ! 543: } ! 544: ! 545: ! 546: /* ContainerLine_Release ! 547: ** --------------------- ! 548: ** ! 549: ** decrement the ref count of the line object. ! 550: ** if the ref count goes to 0, then the line is destroyed. ! 551: ** ! 552: ** Returns the remaining ref count on the object ! 553: */ ! 554: ULONG ContainerLine_Release(LPCONTAINERLINE lpContainerLine) ! 555: { ! 556: ULONG cRef; ! 557: ! 558: OleDbgAssertSz(lpContainerLine->m_cRef > 0,"Release called with cRef == 0"); ! 559: ! 560: /********************************************************************* ! 561: ** OLE2NOTE: when the obj refcnt == 0, then destroy the object. ** ! 562: ** otherwise the object is still in use. ** ! 563: *********************************************************************/ ! 564: ! 565: cRef = --lpContainerLine->m_cRef; ! 566: ! 567: OleDbgOutRefCnt4( ! 568: "ContainerLine_AddRef: cRef--\r\n", ! 569: lpContainerLine, ! 570: cRef ! 571: ); ! 572: ! 573: if (cRef == 0) ! 574: ContainerLine_Destroy(lpContainerLine); ! 575: ! 576: return cRef; ! 577: } ! 578: ! 579: ! 580: /* ContainerLine_QueryInterface ! 581: ** ---------------------------- ! 582: ** ! 583: ** Retrieve a pointer to an interface on the ContainerLine object. ! 584: ** ! 585: ** Returns NOERROR if interface is successfully retrieved. ! 586: ** E_NOINTERFACE if the interface is not supported ! 587: */ ! 588: HRESULT ContainerLine_QueryInterface( ! 589: LPCONTAINERLINE lpContainerLine, ! 590: REFIID riid, ! 591: LPVOID FAR* lplpvObj ! 592: ) ! 593: { ! 594: SCODE sc = E_NOINTERFACE; ! 595: ! 596: /* OLE2NOTE: we must make sure to set all out ptr parameters to NULL. */ ! 597: *lplpvObj = NULL; ! 598: ! 599: if (IsEqualIID(riid, &IID_IUnknown)) { ! 600: OleDbgOut4("ContainerLine_QueryInterface: IUnknown* RETURNED\r\n"); ! 601: ! 602: *lplpvObj = (LPVOID) &lpContainerLine->m_Unknown; ! 603: ContainerLine_AddRef(lpContainerLine); ! 604: sc = S_OK; ! 605: } ! 606: else if (IsEqualIID(riid, &IID_IOleClientSite)) { ! 607: OleDbgOut4("ContainerLine_QueryInterface: IOleClientSite* RETURNED\r\n"); ! 608: ! 609: *lplpvObj = (LPVOID) &lpContainerLine->m_OleClientSite; ! 610: ContainerLine_AddRef(lpContainerLine); ! 611: sc = S_OK; ! 612: } ! 613: else if (IsEqualIID(riid, &IID_IAdviseSink)) { ! 614: OleDbgOut4("ContainerLine_QueryInterface: IAdviseSink* RETURNED\r\n"); ! 615: ! 616: *lplpvObj = (LPVOID) &lpContainerLine->m_AdviseSink; ! 617: ContainerLine_AddRef(lpContainerLine); ! 618: sc = S_OK; ! 619: } ! 620: #if defined( INPLACE_CNTR ) ! 621: else if (IsEqualIID(riid, &IID_IOleWindow) ! 622: || IsEqualIID(riid, &IID_IOleInPlaceSite)) { ! 623: OleDbgOut4("ContainerLine_QueryInterface: IOleInPlaceSite* RETURNED\r\n"); ! 624: ! 625: *lplpvObj = (LPVOID) &lpContainerLine->m_OleInPlaceSite; ! 626: ContainerLine_AddRef(lpContainerLine); ! 627: sc = S_OK; ! 628: } ! 629: #endif // INPLACE_CNTR ! 630: ! 631: OleDbgQueryInterfaceMethod(*lplpvObj); ! 632: ! 633: return ResultFromScode(sc); ! 634: } ! 635: ! 636: ! 637: BOOL ContainerLine_LoadOleObject(LPCONTAINERLINE lpContainerLine) ! 638: { ! 639: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; ! 640: LPSTORAGE lpDocStg = ContainerDoc_GetStg(lpContainerLine->m_lpDoc); ! 641: LPOLECLIENTSITE lpOleClientSite; ! 642: LPMONIKER lpmkObj; ! 643: HRESULT hrErr; ! 644: ! 645: if (lpContainerLine->m_lpOleObj) ! 646: return TRUE; // object already loaded ! 647: ! 648: OLEDBG_BEGIN3("ContainerLine_LoadOleObject\r\n") ! 649: ! 650: /* if object storage is not already open, then open it */ ! 651: if (! lpContainerLine->m_lpStg) { ! 652: lpContainerLine->m_lpStg = OleStdOpenChildStorage( ! 653: lpDocStg, ! 654: lpContainerLine->m_szStgName, ! 655: STGM_READWRITE ! 656: ); ! 657: if (lpContainerLine->m_lpStg == NULL) { ! 658: OleDbgAssertSz( ! 659: lpContainerLine->m_lpStg != NULL, "Error opening child stg"); ! 660: OLEDBG_END3 ! 661: return FALSE; ! 662: } ! 663: } ! 664: ! 665: /* OLE2NOTE: if the OLE object being loaded is in a data transfer ! 666: ** document, then we should NOT pass a IOleClientSite* pointer ! 667: ** to the OleLoad call. This particularly critical if the OLE ! 668: ** object is an OleLink object. If a non-NULL client site is ! 669: ** passed to the OleLoad function, then the link will bind to ! 670: ** the source if its is running. in the situation that we are ! 671: ** loading the object as part of a data transfer document we do ! 672: ** not want this connection to be established. even worse, if ! 673: ** the link source is currently blocked or busy, then this could ! 674: ** hang the system. it is simplest to never pass a ! 675: ** IOleClientSite* when loading an object in a data transfer ! 676: ** document. ! 677: */ ! 678: lpOleClientSite = (lpOutlineDoc->m_fDataTransferDoc ? ! 679: NULL : (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite); ! 680: ! 681: OLEDBG_BEGIN2("OleLoad called\r\n") ! 682: ! 683: hrErr = OleLoad ( ! 684: lpContainerLine->m_lpStg, ! 685: &IID_IOleObject, ! 686: lpOleClientSite, ! 687: (LPVOID FAR*)&lpContainerLine->m_lpOleObj ! 688: ); ! 689: ! 690: OLEDBG_END2 ! 691: ! 692: if (! OleDbgVerifySz(hrErr == NOERROR, "Could not load object!")) { ! 693: OleDbgOutHResult("OleLoad returned", hrErr); ! 694: goto error; ! 695: } ! 696: ! 697: // Cache a pointer to the IViewObject* interface. ! 698: // we need this everytime we draw the object. ! 699: lpContainerLine->m_lpViewObj = (LPVIEWOBJECT)OleStdQueryInterface( ! 700: (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IViewObject); ! 701: if (! lpContainerLine->m_lpViewObj) { ! 702: OleDbgAssert(lpContainerLine->m_lpViewObj); ! 703: goto error; ! 704: } ! 705: ! 706: // Cache a pointer to the IPersistStorage* interface. ! 707: // we need this everytime we save the object. ! 708: lpContainerLine->m_lpPersistStg = (LPPERSISTSTORAGE)OleStdQueryInterface( ! 709: (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IPersistStorage); ! 710: if (! lpContainerLine->m_lpPersistStg) { ! 711: OleDbgAssert(lpContainerLine->m_lpPersistStg); ! 712: goto error; ! 713: } ! 714: ! 715: /* OLE2NOTE: similarly, if the OLE object being loaded is in a data ! 716: ** transfer document, then we do NOT need to setup any advises, ! 717: ** call SetHostNames, SetMoniker, etc. ! 718: */ ! 719: if (lpOleClientSite) { ! 720: /* Setup the Advises (OLE notifications) that we are interested ! 721: ** in receiving. ! 722: */ ! 723: OleStdSetupAdvises( ! 724: lpContainerLine->m_lpOleObj, ! 725: lpContainerLine->m_dwDrawAspect, ! 726: (LPSTR)APPNAME, ! 727: lpOutlineDoc->m_lpszDocTitle, ! 728: (LPADVISESINK)&lpContainerLine->m_AdviseSink ! 729: ); ! 730: ! 731: /* OLE2NOTE: if the OLE object has a moniker assigned, we need to ! 732: ** inform the object by calling IOleObject::SetMoniker. this ! 733: ** will force the OLE object to register in the ! 734: ** RunningObjectTable when it enters the running state. ! 735: */ ! 736: if (lpContainerLine->m_fMonikerAssigned) { ! 737: lpmkObj = ContainerLine_GetRelMoniker( ! 738: lpContainerLine, ! 739: GETMONIKER_ONLYIFTHERE ! 740: ); ! 741: ! 742: if (lpmkObj) { ! 743: OLEDBG_BEGIN2("IOleObject::SetMoniker called\r\n") ! 744: lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker( ! 745: lpContainerLine->m_lpOleObj, ! 746: OLEWHICHMK_OBJREL, ! 747: lpmkObj ! 748: ); ! 749: OLEDBG_END2 ! 750: OleStdRelease((LPUNKNOWN)lpmkObj); ! 751: } ! 752: } ! 753: ! 754: /* get the Short form of the user type name of the object. this ! 755: ** is used all the time when we have to build the object ! 756: ** verb menu. we will cache this information to make it ! 757: ** quicker to build the verb menu. ! 758: */ ! 759: OLEDBG_BEGIN2("IOleObject::GetUserType called\r\n") ! 760: lpContainerLine->m_lpOleObj->lpVtbl->GetUserType( ! 761: lpContainerLine->m_lpOleObj, ! 762: USERCLASSTYPE_SHORT, ! 763: (LPSTR FAR*)&lpContainerLine->m_lpszShortType ! 764: ); ! 765: OLEDBG_END2 ! 766: ! 767: /* OLE2NOTE: if the object we just loaded is a link then it ! 768: ** might have immediately bound to its link source if it was ! 769: ** already running. when this happens the link will get an ! 770: ** immediate update of data if the link is automatic. in ! 771: ** this situation, it is possible that the extents of the ! 772: ** linked object have changed. ! 773: */ ! 774: if (lpContainerLine->m_fIsLink) { ! 775: if (OleIsRunning(lpContainerLine->m_lpOleObj)) { ! 776: ContainerLine_UpdateExtent(lpContainerLine, NULL); ! 777: } ! 778: } ! 779: #if defined( INPLACE_CNTR ) ! 780: /* OLE2NOTE: an inside-out container should check if the object ! 781: ** is an inside-out and prefers to be activated when visible ! 782: ** type of object. if so, the object should be immediately ! 783: ** activated in-place, BUT NOT UIActived. ! 784: */ ! 785: else if (g_fInsideOutContainer && ! 786: lpContainerLine->m_dwDrawAspect == DVASPECT_CONTENT) { ! 787: DWORD mstat; ! 788: OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") ! 789: lpContainerLine->m_lpOleObj->lpVtbl->GetMiscStatus( ! 790: lpContainerLine->m_lpOleObj, ! 791: DVASPECT_CONTENT, ! 792: (DWORD FAR*)&mstat ! 793: ); ! 794: OLEDBG_END2 ! 795: ! 796: lpContainerLine->m_fInsideOutObj = (BOOL) ! 797: (mstat & (OLEMISC_INSIDEOUT|OLEMISC_ACTIVATEWHENVISIBLE)); ! 798: ! 799: if ( lpContainerLine->m_fInsideOutObj ) { ! 800: HWND hWndDoc = OutlineDoc_GetWindow(lpOutlineDoc); ! 801: ! 802: ContainerLine_DoVerb( ! 803: lpContainerLine,OLEIVERB_INPLACEACTIVATE,FALSE,FALSE); ! 804: ! 805: /* OLE2NOTE: following this DoVerb(INPLACEACTIVATE) the ! 806: ** object may have taken focus. but because the ! 807: ** object is NOT UIActive it should NOT have focus. ! 808: ** we will make sure our document has focus. ! 809: */ ! 810: SetFocus(hWndDoc); ! 811: } ! 812: } ! 813: #endif // INPLACE_CNTR ! 814: OLEDBG_END2 ! 815: ! 816: } ! 817: ! 818: OLEDBG_END2 ! 819: return TRUE; ! 820: ! 821: error: ! 822: OLEDBG_END2 ! 823: return FALSE; ! 824: } ! 825: ! 826: ! 827: /* ContainerLine_CloseOleObject ! 828: ** ---------------------------- ! 829: ** Close the OLE object associated with the ContainerLine. ! 830: ** ! 831: ** Closing the object forces the object to transition from the ! 832: ** running state to the loaded state. if the object was not running, ! 833: ** then there is no effect. it is necessary to close the OLE object ! 834: ** before releasing the pointers to the OLE object. ! 835: ** ! 836: ** Returns TRUE if successfully closed, ! 837: ** FALSE if closing was aborted. ! 838: */ ! 839: BOOL ContainerLine_CloseOleObject(LPCONTAINERLINE lpContainerLine) ! 840: { ! 841: HRESULT hrErr; ! 842: SCODE sc; ! 843: ! 844: if (lpContainerLine->m_lpOleObj) { ! 845: ! 846: OLEDBG_BEGIN2("IOleObject::Close called\r\n") ! 847: hrErr = lpContainerLine->m_lpOleObj->lpVtbl->Close( ! 848: lpContainerLine->m_lpOleObj, ! 849: OLECLOSE_SAVEIFDIRTY ! 850: ); ! 851: OLEDBG_END2 ! 852: ! 853: if (hrErr != NOERROR) { ! 854: OleDbgOutHResult("IOleObject::Close returned", hrErr); ! 855: sc = GetScode(hrErr); ! 856: if (sc == RPC_E_CALL_REJECTED || sc==OLE_E_PROMPTSAVECANCELLED) { ! 857: return FALSE; // object aborted shutdown ! 858: } ! 859: } ! 860: } ! 861: return TRUE; ! 862: } ! 863: ! 864: ! 865: /* ContainerLine_UnloadOleObject ! 866: ** ----------------------------- ! 867: ** Close the OLE object associated with the ContainerLine and ! 868: ** release all pointer held to the object. ! 869: ** ! 870: ** Closing the object forces the object to transition from the ! 871: ** running state to the loaded state. if the object was not running, ! 872: ** then there is no effect. it is necessary to close the OLE object ! 873: ** before releasing the pointers to the OLE object. releasing all ! 874: ** pointers to the object allows the object to transition from ! 875: ** loaded to unloaded (or passive). ! 876: */ ! 877: void ContainerLine_UnloadOleObject(LPCONTAINERLINE lpContainerLine) ! 878: { ! 879: if (lpContainerLine->m_lpOleObj) { ! 880: ! 881: OLEDBG_BEGIN2("IOleObject::Close called\r\n") ! 882: lpContainerLine->m_lpOleObj->lpVtbl->Close( ! 883: lpContainerLine->m_lpOleObj, ! 884: OLECLOSE_SAVEIFDIRTY ! 885: ); ! 886: OLEDBG_END2 ! 887: ! 888: OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpOleObj); ! 889: lpContainerLine->m_lpOleObj = NULL; ! 890: ! 891: if (lpContainerLine->m_lpViewObj) { ! 892: OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpViewObj); ! 893: lpContainerLine->m_lpViewObj = NULL; ! 894: } ! 895: if (lpContainerLine->m_lpPersistStg) { ! 896: OleStdRelease((LPUNKNOWN)lpContainerLine->m_lpPersistStg); ! 897: lpContainerLine->m_lpPersistStg = NULL; ! 898: } ! 899: } ! 900: } ! 901: ! 902: ! 903: /* ContainerLine_Delete ! 904: ** -------------------- ! 905: ** Delete the ContainerLine. ! 906: ** ! 907: ** NOTE: we can NOT directly destroy the memory for the ! 908: ** ContainerLine; the ContainerLine maintains a reference count. a ! 909: ** non-zero reference count indicates that the object is still ! 910: ** in-use. The OleObject keeps a reference-counted pointer to the ! 911: ** ClientLine object. we must take the actions necessary so that the ! 912: ** ContainerLine object receives Releases for outstanding ! 913: ** references. when the reference count of the ContainerLine reaches ! 914: ** zero, then the memory for the object will actually be destroyed ! 915: ** (ContainerLine_Destroy called). ! 916: ** ! 917: */ ! 918: void ContainerLine_Delete(LPCONTAINERLINE lpContainerLine) ! 919: { ! 920: OLEDBG_BEGIN2("ContainerLine_Delete\r\n") ! 921: ! 922: #if defined( INPLACE_CNTR ) ! 923: if (lpContainerLine == lpContainerLine->m_lpDoc->m_lpLastIpActiveLine) ! 924: lpContainerLine->m_lpDoc->m_lpLastIpActiveLine = NULL; ! 925: if (lpContainerLine == lpContainerLine->m_lpDoc->m_lpLastUIActiveLine) ! 926: lpContainerLine->m_lpDoc->m_lpLastUIActiveLine = NULL; ! 927: #endif ! 928: ! 929: /* OLE2NOTE: in order to have a stable line object during the ! 930: ** process of deleting, we intially AddRef the line ref cnt and ! 931: ** later Release it. This initial AddRef is artificial; it is ! 932: ** simply done to guarantee that our object does not destroy ! 933: ** itself until the END of this routine. ! 934: */ ! 935: ContainerLine_AddRef(lpContainerLine); ! 936: ! 937: // Unload the loaded OLE object ! 938: if (lpContainerLine->m_lpOleObj) ! 939: ContainerLine_UnloadOleObject(lpContainerLine); ! 940: ! 941: /* OLE2NOTE: we can NOT directly free the memory for the ContainerLine ! 942: ** data structure until everyone holding on to a pointer to our ! 943: ** ClientSite interface and IAdviseSink interface has released ! 944: ** their pointers. There is one refcnt on the ContainerLine object ! 945: ** which is held by the container itself. we will release this ! 946: ** refcnt here. ! 947: */ ! 948: ContainerLine_Release(lpContainerLine); ! 949: ! 950: ContainerLine_Release(lpContainerLine); // release artificial AddRef above ! 951: OLEDBG_END2 ! 952: } ! 953: ! 954: ! 955: /* ContainerLine_Destroy ! 956: ** --------------------- ! 957: ** Destroy (Free) the memory used by a ContainerLine structure. ! 958: ** This function is called when the ref count of the ContainerLine goes ! 959: ** to zero. the ref cnt goes to zero after ContainerLine_Delete forces ! 960: ** the OleObject to unload and release its pointers to the ! 961: ** ContainerLine IOleClientSite and IAdviseSink interfaces. ! 962: */ ! 963: ! 964: void ContainerLine_Destroy(LPCONTAINERLINE lpContainerLine) ! 965: { ! 966: LPUNKNOWN lpTmpObj; ! 967: ! 968: OLEDBG_BEGIN2("ContainerLine_Destroy\r\n") ! 969: ! 970: // Release the storage opened for the OLE object ! 971: if (lpContainerLine->m_lpStg) { ! 972: lpTmpObj = (LPUNKNOWN)lpContainerLine->m_lpStg; ! 973: lpContainerLine->m_lpStg = NULL; ! 974: ! 975: OleStdVerifyRelease(lpTmpObj, "Object stg not released"); ! 976: } ! 977: ! 978: if (lpContainerLine->m_lpszShortType) ! 979: OleStdFreeString(lpContainerLine->m_lpszShortType, NULL); ! 980: ! 981: Delete(lpContainerLine); // Free the memory for the structure itself ! 982: OLEDBG_END2 ! 983: } ! 984: ! 985: ! 986: /* ContainerLine_CopyToDoc ! 987: * ----------------------- ! 988: * ! 989: * Copy a ContainerLine to another Document (usually ClipboardDoc) ! 990: */ ! 991: BOOL ContainerLine_CopyToDoc( ! 992: LPCONTAINERLINE lpSrcLine, ! 993: LPOUTLINEDOC lpDestDoc, ! 994: int nIndex ! 995: ) ! 996: { ! 997: LPCONTAINERLINE lpDestLine = NULL; ! 998: LPLINELIST lpDestLL = &lpDestDoc->m_LineList; ! 999: HDC hDC; ! 1000: HRESULT hrErr; ! 1001: BOOL fStatus; ! 1002: LPSTORAGE lpDestDocStg = ((LPCONTAINERDOC)lpDestDoc)->m_lpStg; ! 1003: LPSTORAGE lpDestObjStg = NULL; ! 1004: ! 1005: lpDestLine = (LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); ! 1006: if (lpDestLine == NULL) { ! 1007: OleDbgAssertSz( ! 1008: lpDestLine!=NULL, "Error allocating ContainerLine"); ! 1009: return FALSE; ! 1010: } ! 1011: ! 1012: hDC = LineList_GetDC(lpDestLL); ! 1013: ContainerLine_Init(lpDestLine, ((LPLINE)lpSrcLine)->m_nTabLevel, hDC); ! 1014: LineList_ReleaseDC(lpDestLL, hDC); ! 1015: ! 1016: /* OLE2NOTE: In order to have a stable ContainerLine object we must ! 1017: ** AddRef the object's refcnt. this will be later released when ! 1018: ** the ContainerLine is deleted. ! 1019: */ ! 1020: ContainerLine_AddRef(lpDestLine); ! 1021: ! 1022: lpDestLine->m_lpDoc = (LPCONTAINERDOC)lpDestDoc; ! 1023: ! 1024: // Copy data of the original source ContainerLine. ! 1025: ((LPLINE)lpDestLine)->m_nWidthInHimetric = ! 1026: ((LPLINE)lpSrcLine)->m_nWidthInHimetric; ! 1027: ((LPLINE)lpDestLine)->m_nHeightInHimetric = ! 1028: ((LPLINE)lpSrcLine)->m_nHeightInHimetric; ! 1029: lpDestLine->m_fMonikerAssigned = lpSrcLine->m_fMonikerAssigned; ! 1030: lpDestLine->m_dwDrawAspect = lpSrcLine->m_dwDrawAspect; ! 1031: lpDestLine->m_sizeInHimetric = lpSrcLine->m_sizeInHimetric; ! 1032: lpDestLine->m_fIsLink = lpSrcLine->m_fIsLink; ! 1033: ! 1034: ! 1035: /* We must create a new sub-storage for the embedded object within ! 1036: ** the destination document's storage. We will first attempt to ! 1037: ** use the same storage name as the source line. if this name is ! 1038: ** in use, then we will allocate a new name. in this way we try ! 1039: ** to keep the name associated with the OLE object unchanged ! 1040: ** through a Cut/Paste operation. ! 1041: */ ! 1042: lpDestObjStg = OleStdCreateChildStorage( ! 1043: lpDestDocStg, ! 1044: lpSrcLine->m_szStgName ! 1045: ); ! 1046: if (lpDestObjStg) { ! 1047: lstrcpy(lpDestLine->m_szStgName, lpSrcLine->m_szStgName); ! 1048: } else { ! 1049: /* the original name was in use, make up a new name. */ ! 1050: ContainerDoc_GetNextStgName( ! 1051: (LPCONTAINERDOC)lpDestDoc, ! 1052: lpDestLine->m_szStgName, ! 1053: sizeof(lpDestLine->m_szStgName) ! 1054: ); ! 1055: lpDestObjStg = OleStdCreateChildStorage( ! 1056: lpDestDocStg, ! 1057: lpDestLine->m_szStgName ! 1058: ); ! 1059: } ! 1060: if (! OleDbgVerifySz(lpDestObjStg != NULL, "Error creating child stg")) ! 1061: goto error; ! 1062: ! 1063: // Copy over storage of the embedded object itself ! 1064: ! 1065: if (! lpSrcLine->m_lpOleObj) { ! 1066: ! 1067: /***************************************************************** ! 1068: ** CASE 1: object is NOT loaded. ! 1069: ** because the object is not loaded, we can simply copy the ! 1070: ** object's current storage to the new storage. ! 1071: *****************************************************************/ ! 1072: ! 1073: /* if current object storage is not already open, then open it */ ! 1074: if (! lpSrcLine->m_lpStg) { ! 1075: LPSTORAGE lpSrcDocStg = lpSrcLine->m_lpDoc->m_lpStg; ! 1076: ! 1077: if (! lpSrcDocStg) goto error; ! 1078: ! 1079: // open object storage. ! 1080: lpSrcLine->m_lpStg = OleStdOpenChildStorage( ! 1081: lpSrcDocStg, ! 1082: lpSrcLine->m_szStgName, ! 1083: STGM_READWRITE ! 1084: ); ! 1085: if (! OleDbgVerifySz(lpSrcLine->m_lpStg != NULL, ! 1086: "Error opening child stg")) ! 1087: goto error; ! 1088: } ! 1089: ! 1090: hrErr = lpSrcLine->m_lpStg->lpVtbl->CopyTo( ! 1091: lpSrcLine->m_lpStg, ! 1092: 0, ! 1093: NULL, ! 1094: NULL, ! 1095: lpDestObjStg ! 1096: ); ! 1097: if (hrErr != NOERROR) { ! 1098: OleDbgOutHResult("WARNING: lpSrcObjStg->CopyTo returned", hrErr); ! 1099: goto error; ! 1100: } ! 1101: ! 1102: fStatus = OleStdCommitStorage(lpDestObjStg); ! 1103: ! 1104: } else { ! 1105: ! 1106: /***************************************************************** ! 1107: ** CASE 2: object IS loaded. ! 1108: ** we must tell the object to save into the new storage. ! 1109: *****************************************************************/ ! 1110: ! 1111: hrErr = ContainerLine_SaveOleObject( ! 1112: lpSrcLine, ! 1113: lpDestObjStg, ! 1114: FALSE, /* fSameAsLoad */ ! 1115: FALSE, /* fRemember */ ! 1116: TRUE /* fForceUpdate */ ! 1117: ); ! 1118: ! 1119: if (hrErr != NOERROR) ! 1120: goto error; ! 1121: } ! 1122: ! 1123: OutlineDoc_AddLine(lpDestDoc, (LPLINE)lpDestLine, nIndex); ! 1124: OleStdVerifyRelease( ! 1125: (LPUNKNOWN)lpDestObjStg, ! 1126: "Copied object stg not released" ! 1127: ); ! 1128: ! 1129: return TRUE; ! 1130: ! 1131: error: ! 1132: ! 1133: // Delete any partially created storage. ! 1134: if (lpDestObjStg) { ! 1135: OleStdVerifyRelease( ! 1136: (LPUNKNOWN)lpDestObjStg, ! 1137: "Copied object stg not released" ! 1138: ); ! 1139: ! 1140: lpDestDocStg->lpVtbl->DestroyElement( ! 1141: lpDestDocStg, ! 1142: lpDestLine->m_szStgName ! 1143: ); ! 1144: lpDestLine->m_szStgName[0] = '\0'; ! 1145: } ! 1146: ! 1147: // destroy partially created ContainerLine ! 1148: if (lpDestLine) ! 1149: ContainerLine_Delete(lpDestLine); ! 1150: return FALSE; ! 1151: } ! 1152: ! 1153: ! 1154: /* ContainerLine_UpdateExtent ! 1155: ** -------------------------- ! 1156: ** Update the size of the ContainerLine because the extents of the ! 1157: ** object may have changed. ! 1158: ** ! 1159: ** NOTE: because we are using a Windows OwnerDraw ListBox, we must ! 1160: ** constrain the maximum possible height of a line. the ListBox has ! 1161: ** a limitation (unfortunately) that no line can become larger than ! 1162: ** 255 pixels. thus we force the object to scale maintaining its ! 1163: ** aspect ratio if this maximum line height limit is reached. the ! 1164: ** actual maximum size for an object at 100% Zoom is ! 1165: ** 255-2*LINE_BOUNDARY_WIDTH. ! 1166: ** ! 1167: ** RETURNS TRUE -- if the extents of the object changed ! 1168: ** FALSE -- if the extents did NOT change ! 1169: */ ! 1170: BOOL ContainerLine_UpdateExtent( ! 1171: LPCONTAINERLINE lpContainerLine, ! 1172: LPSIZEL lpsizelHim ! 1173: ) ! 1174: { ! 1175: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; ! 1176: LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); ! 1177: LPLINE lpLine = (LPLINE)lpContainerLine; ! 1178: int nIndex = LineList_GetLineIndex(lpLL, lpLine); ! 1179: UINT nOrgWidthInHimetric = lpLine->m_nWidthInHimetric; ! 1180: UINT nOrgHeightInHimetric = lpLine->m_nHeightInHimetric; ! 1181: BOOL fWidthChanged = FALSE; ! 1182: BOOL fHeightChanged = FALSE; ! 1183: SIZEL sizelHim; ! 1184: HRESULT hrErr; ! 1185: ! 1186: if (!lpContainerLine || !lpContainerLine->m_lpOleObj) ! 1187: return FALSE; ! 1188: ! 1189: OLEDBG_BEGIN3("ContainerLine_UpdateExtent\r\n"); ! 1190: ! 1191: lpContainerLine->m_fDoGetExtent = FALSE; ! 1192: ! 1193: if (! lpsizelHim) { ! 1194: OLEDBG_BEGIN2("IOleObject::GetExtent called\r\n") ! 1195: hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetExtent( ! 1196: lpContainerLine->m_lpOleObj, ! 1197: lpContainerLine->m_dwDrawAspect, ! 1198: (LPSIZEL)&sizelHim ! 1199: ); ! 1200: OLEDBG_END2 ! 1201: if (hrErr != NOERROR) ! 1202: sizelHim.cx = sizelHim.cy = 0; ! 1203: ! 1204: lpsizelHim = (LPSIZEL)&sizelHim; ! 1205: } ! 1206: ! 1207: if (lpsizelHim->cx == lpContainerLine->m_sizeInHimetric.cx && ! 1208: lpsizelHim->cy == lpContainerLine->m_sizeInHimetric.cy) { ! 1209: goto noupdate; ! 1210: } ! 1211: ! 1212: if (lpsizelHim->cx > 0 || lpsizelHim->cy > 0) { ! 1213: lpContainerLine->m_sizeInHimetric = *lpsizelHim; ! 1214: } else { ! 1215: /* object does not have any extents; let's use our container ! 1216: ** chosen arbitrary size for OLE objects. ! 1217: */ ! 1218: lpContainerLine->m_sizeInHimetric.cx = (long)DEFOBJWIDTH; ! 1219: lpContainerLine->m_sizeInHimetric.cy = (long)DEFOBJHEIGHT; ! 1220: } ! 1221: ! 1222: ContainerLine_CalcExtents( ! 1223: lpContainerLine, ! 1224: (LPSIZEL)&lpContainerLine->m_sizeInHimetric); ! 1225: ! 1226: // if height of object changed, then reset the height of line in LineList ! 1227: if (nOrgHeightInHimetric != lpLine->m_nHeightInHimetric) { ! 1228: LineList_SetLineHeight(lpLL, nIndex, lpLine->m_nHeightInHimetric); ! 1229: fHeightChanged = TRUE; ! 1230: } ! 1231: ! 1232: fWidthChanged = LineList_RecalcMaxLineWidthInHimetric( ! 1233: lpLL, ! 1234: nOrgWidthInHimetric ! 1235: ); ! 1236: fWidthChanged |= (nOrgWidthInHimetric != lpLine->m_nWidthInHimetric); ! 1237: ! 1238: if (fHeightChanged || fWidthChanged) { ! 1239: OutlineDoc_ForceRedraw(lpOutlineDoc, TRUE); ! 1240: ! 1241: // mark ContainerDoc as now dirty ! 1242: OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, TRUE); ! 1243: } ! 1244: ! 1245: OLEDBG_END3 ! 1246: return TRUE; ! 1247: ! 1248: noupdate: ! 1249: OLEDBG_END3 ! 1250: return FALSE; // No UPDATE necessary ! 1251: } ! 1252: ! 1253: ! 1254: /* ContainerLine_DoVerb ! 1255: ** -------------------- ! 1256: ** Activate the OLE object and perform a specific verb. ! 1257: */ ! 1258: BOOL ContainerLine_DoVerb(LPCONTAINERLINE lpContainerLine, LONG iVerb, BOOL fMessage, BOOL fAction) ! 1259: { ! 1260: HRESULT hrErr; ! 1261: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; ! 1262: RECT rcPosRect; ! 1263: ! 1264: OLEDBG_BEGIN3("ContainerLine_DoVerb\r\n") ! 1265: /* if object is not already loaded, then load it now. objects are ! 1266: ** loaded lazily in this manner. ! 1267: */ ! 1268: if (! lpContainerLine->m_lpOleObj) ! 1269: ContainerLine_LoadOleObject(lpContainerLine); ! 1270: ! 1271: if (! lpContainerLine->m_lpOleObj) { ! 1272: OleDbgAssertSz(lpContainerLine->m_lpOleObj != NULL, ! 1273: "OLE object not loaded"); ! 1274: goto error; ! 1275: } ! 1276: ! 1277: #if defined( INPLACE_CNTR ) ! 1278: /* OLE2NOTE: we want to keep only 1 inplace server active at any ! 1279: ** given time. so when we start to do a DoVerb on another line, ! 1280: ** then we want to shut down the previously activated server. in ! 1281: ** this way we keep at most one inplace server active at a time. ! 1282: */ ! 1283: if (!g_fInsideOutContainer) { ! 1284: ContainerDoc_ShutDownLastInPlaceServerIfNotNeeded( ! 1285: lpContainerLine->m_lpDoc, lpContainerLine); ! 1286: } ! 1287: #endif // INPLACE_CNTR ! 1288: ! 1289: ContainerLine_GetOleObjectRectInPixels( ! 1290: lpContainerLine, ! 1291: (LPRECT)&rcPosRect ! 1292: ); ! 1293: ! 1294: // run the object ! 1295: hrErr = ContainerLine_RunOleObject(lpContainerLine); ! 1296: if (hrErr != NOERROR) ! 1297: goto error; ! 1298: ! 1299: /* Tell object server to perform a "verb". */ ! 1300: OLEDBG_BEGIN2("IOleObject::DoVerb called\r\n") ! 1301: hrErr = lpContainerLine->m_lpOleObj->lpVtbl->DoVerb ( ! 1302: lpContainerLine->m_lpOleObj, ! 1303: iVerb, ! 1304: NULL, ! 1305: (LPOLECLIENTSITE)&lpContainerLine->m_OleClientSite, ! 1306: -1, ! 1307: OutlineDoc_GetWindow(lpOutlineDoc), ! 1308: (LPCRECT)&rcPosRect ! 1309: ); ! 1310: OLEDBG_END2 ! 1311: ! 1312: /* OLE2NOTE: IOleObject::DoVerb may return a success code ! 1313: ** OLE_S_INVALIDVERB. this SCODE should NOT be considered an ! 1314: ** error; thus it is important to use the "FAILED" macro to ! 1315: ** check for an error SCODE. ! 1316: */ ! 1317: if (FAILED(GetScode(hrErr))) { ! 1318: OleDbgOutHResult("WARNING: lpOleObj->DoVerb returned", hrErr); ! 1319: goto error; ! 1320: } ! 1321: ! 1322: OLEDBG_END3 ! 1323: return TRUE; ! 1324: ! 1325: error: ! 1326: if (lpContainerLine->m_fIsLink) ! 1327: lpContainerLine->m_fLinkUnavailable = TRUE; ! 1328: ! 1329: /* OLE2NOTE: if an error occurs we must give the appropriate error ! 1330: ** message box. there are many potential errors that can occur. ! 1331: ** the OLE2.0 user model has specific guidelines as to the ! 1332: ** dialogs that should be displayed given the various potential ! 1333: ** errors (eg. server not registered, unavailable link source. ! 1334: ** the OLE2UI library includes support for most of the ! 1335: ** recommended message dialogs. (see OleUIPrompUser function) ! 1336: */ ! 1337: if (fMessage) { ! 1338: ProcessError(hrErr, lpContainerLine, fAction); ! 1339: } ! 1340: ! 1341: OLEDBG_END3 ! 1342: return FALSE; ! 1343: } ! 1344: ! 1345: ! 1346: /* ContainerLine_GetOleObject ! 1347: ** -------------------------- ! 1348: ** return pointer to desired interface of embedded/linked object. ! 1349: ** ! 1350: ** NOTE: this function causes an AddRef to the object. when the caller is ! 1351: ** finished with the object, it must call Release. ! 1352: ** this function does not AddRef the ContainerLine object. ! 1353: */ ! 1354: LPUNKNOWN ContainerLine_GetOleObject( ! 1355: LPCONTAINERLINE lpContainerLine, ! 1356: REFIID riid ! 1357: ) ! 1358: { ! 1359: /* if object is not already loaded, then load it now. objects are ! 1360: ** loaded lazily in this manner. ! 1361: */ ! 1362: if (! lpContainerLine->m_lpOleObj) ! 1363: ContainerLine_LoadOleObject(lpContainerLine); ! 1364: ! 1365: if (lpContainerLine->m_lpOleObj) ! 1366: return OleStdQueryInterface( ! 1367: (LPUNKNOWN)lpContainerLine->m_lpOleObj, ! 1368: riid ! 1369: ); ! 1370: else ! 1371: return NULL; ! 1372: } ! 1373: ! 1374: ! 1375: ! 1376: /* ContainerLine_RunOleObject ! 1377: ** -------------------------- ! 1378: ** Load and run the object. Upon running and if size of object has changed, ! 1379: ** use SetExtent to change to new size. ! 1380: ** ! 1381: */ ! 1382: HRESULT ContainerLine_RunOleObject(LPCONTAINERLINE lpContainerLine) ! 1383: { ! 1384: LPUNKNOWN lpUnk; ! 1385: LPLINE lpLine = (LPLINE)lpContainerLine; ! 1386: SIZEL sizelNew; ! 1387: HRESULT hrErr; ! 1388: HCURSOR hPrevCursor; ! 1389: ! 1390: if (! lpContainerLine) ! 1391: return NOERROR; ! 1392: ! 1393: if (lpContainerLine->m_lpOleObj && ! 1394: OleIsRunning(lpContainerLine->m_lpOleObj)) ! 1395: return NOERROR; // object already running ! 1396: ! 1397: // this may take a while, put up hourglass cursor ! 1398: hPrevCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); ! 1399: ! 1400: OLEDBG_BEGIN3("ContainerLine_RunOleObject\r\n") ! 1401: ! 1402: lpUnk = ContainerLine_GetOleObject(lpContainerLine, &IID_IUnknown); ! 1403: ! 1404: OLEDBG_BEGIN2("OleRun called\r\n") ! 1405: hrErr = OleRun(lpUnk); // FORCE object to RUN ! 1406: OLEDBG_END2 ! 1407: ! 1408: OleStdRelease(lpUnk); ! 1409: ! 1410: SetCursor(hPrevCursor); // restore original cursor ! 1411: ! 1412: if (hrErr != NOERROR) { ! 1413: OleDbgOutHResult("OleRun returned", hrErr); ! 1414: OLEDBG_END3 ! 1415: return hrErr; ! 1416: } ! 1417: ! 1418: sizelNew.cx = lpLine->m_nWidthInHimetric - XformWidthInPixelsToHimetric( ! 1419: NULL, LINE_BOUNDARY_WIDTH * 2); ! 1420: sizelNew.cy = lpLine->m_nHeightInHimetric - XformHeightInPixelsToHimetric( ! 1421: NULL, LINE_BOUNDARY_WIDTH * 2); ! 1422: ! 1423: if ((sizelNew.cx != lpContainerLine->m_sizeInHimetric.cx) || ! 1424: (sizelNew.cy != lpContainerLine->m_sizeInHimetric.cy)) { ! 1425: ! 1426: OLEDBG_BEGIN2("IOleObject::SetExtent called\r\n") ! 1427: ! 1428: lpContainerLine->m_lpOleObj->lpVtbl->SetExtent( ! 1429: lpContainerLine->m_lpOleObj, ! 1430: lpContainerLine->m_dwDrawAspect, ! 1431: (LPSIZEL)&sizelNew); ! 1432: ! 1433: OLEDBG_END2 ! 1434: ! 1435: } ! 1436: ! 1437: OLEDBG_END3 ! 1438: return NOERROR; ! 1439: ! 1440: } ! 1441: ! 1442: ! 1443: /* ContainerLine_IsOleLink ! 1444: ** ----------------------- ! 1445: ** ! 1446: ** return TRUE if the ContainerLine has an OleLink. ! 1447: ** FALSE if the ContainerLine has an embedding ! 1448: */ ! 1449: BOOL ContainerLine_IsOleLink(LPCONTAINERLINE lpContainerLine) ! 1450: { ! 1451: if (!lpContainerLine) ! 1452: return FALSE; ! 1453: ! 1454: return lpContainerLine->m_fIsLink; ! 1455: } ! 1456: ! 1457: ! 1458: /* ContainerLine_Draw ! 1459: ** ------------------ ! 1460: ** ! 1461: ** Draw a ContainerLine object on a DC. ! 1462: ** ! 1463: ** Parameters: ! 1464: ** hDC - DC to which the line will be drawn ! 1465: ** lpRect - the object rect in logical coordinates ! 1466: */ ! 1467: void ContainerLine_Draw( ! 1468: LPCONTAINERLINE lpContainerLine, ! 1469: HDC hDC, ! 1470: LPRECT lpRect ! 1471: ) ! 1472: { ! 1473: LPLINE lpLine = (LPLINE) lpContainerLine; ! 1474: HRESULT hrErr = NOERROR; ! 1475: RECTL rclHim; ! 1476: RECT rcHim; ! 1477: ! 1478: /* if object is not already loaded, then load it now. objects are ! 1479: ** loaded lazily in this manner. ! 1480: */ ! 1481: if (! lpContainerLine->m_lpOleObj) ! 1482: ContainerLine_LoadOleObject(lpContainerLine); ! 1483: ! 1484: if (! lpContainerLine->m_lpViewObj) { ! 1485: lpContainerLine->m_lpViewObj = (LPVIEWOBJECT)OleStdQueryInterface( ! 1486: (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IViewObject); ! 1487: if (! lpContainerLine->m_lpViewObj) { ! 1488: OleDbgAssert(lpContainerLine->m_lpViewObj); ! 1489: return; // Error: no IViewObject* available ! 1490: } ! 1491: } ! 1492: ! 1493: /* construct bounds rectangle for the object. ! 1494: ** offset origin for object to correct tab indentation ! 1495: */ ! 1496: rclHim.left = (long) lpRect->left; ! 1497: rclHim.bottom = (long) lpRect->bottom; ! 1498: rclHim.top = (long) lpRect->top; ! 1499: rclHim.right = (long) lpRect->right; ! 1500: ! 1501: rclHim.left += (long) ((LPLINE)lpContainerLine)->m_nTabWidthInHimetric; ! 1502: rclHim.right += (long) ((LPLINE)lpContainerLine)->m_nTabWidthInHimetric; ! 1503: ! 1504: #if defined( INPLACE_CNTR ) ! 1505: /* OLE2NOTE: if the OLE object is currently does has a visible in-place ! 1506: ** window, then we do NOT want to draw on top of its window. ! 1507: ** this could interfere with the object's display. ! 1508: */ ! 1509: if ( !lpContainerLine->m_fIpVisible ) ! 1510: #endif ! 1511: { ! 1512: hrErr = lpContainerLine->m_lpViewObj->lpVtbl->Draw( ! 1513: lpContainerLine->m_lpViewObj, ! 1514: lpContainerLine->m_dwDrawAspect, ! 1515: -1, ! 1516: NULL, ! 1517: NULL, ! 1518: NULL, ! 1519: hDC, ! 1520: (LPRECTL)&rclHim, ! 1521: (LPRECTL)&rclHim, ! 1522: NULL, ! 1523: 0 ! 1524: ); ! 1525: if (hrErr != NOERROR) ! 1526: OleDbgOutHResult("IViewObject::Draw returned", hrErr); ! 1527: ! 1528: if (lpContainerLine->m_fObjWinOpen) { ! 1529: ! 1530: rcHim.left = (int) rclHim.left; ! 1531: rcHim.top = (int) rclHim.top; ! 1532: rcHim.right = (int) rclHim.right; ! 1533: rcHim.bottom = (int) rclHim.bottom; ! 1534: ! 1535: /* OLE2NOTE: if the object servers window is Open (ie. not active ! 1536: ** in-place) then we must shade the object in our document to ! 1537: ** indicate to the user that the object is open elsewhere. ! 1538: */ ! 1539: OleUIDrawShading((LPRECT)&rcHim, hDC, OLEUI_SHADE_FULLRECT, 0); ! 1540: } ! 1541: } ! 1542: return; ! 1543: } ! 1544: ! 1545: ! 1546: void ContainerLine_DrawSelHilight( ! 1547: LPCONTAINERLINE lpContainerLine, ! 1548: HDC hDC, // MM_TEXT mode ! 1549: LPRECT lprcPix, // listbox rect ! 1550: UINT itemAction, ! 1551: UINT itemState ! 1552: ) ! 1553: { ! 1554: LPLINE lpLine = (LPLINE)lpContainerLine; ! 1555: RECT rcObj; ! 1556: DWORD dwFlags = OLEUI_HANDLES_INSIDE | OLEUI_HANDLES_USEINVERSE; ! 1557: int nHandleSize; ! 1558: LPCONTAINERDOC lpContainerDoc; ! 1559: ! 1560: if (!lpContainerLine || !hDC || !lprcPix) ! 1561: return; ! 1562: ! 1563: lpContainerDoc = lpContainerLine->m_lpDoc; ! 1564: ! 1565: // Get size of OLE object ! 1566: ContainerLine_GetOleObjectRectInPixels(lpContainerLine, (LPRECT)&rcObj); ! 1567: ! 1568: InflateRect(&rcObj, 1, 1); // get feedback rect ! 1569: nHandleSize = GetProfileInt("windows", "oleinplaceborderwidth", ! 1570: DEFAULT_HATCHBORDER_WIDTH) + 1; ! 1571: ! 1572: if (itemAction & ODA_SELECT) { ! 1573: // check if there is a selection state change ! 1574: if (itemState & ODS_SELECTED) { ! 1575: if (!lpLine->m_fSelected) { ! 1576: lpLine->m_fSelected = TRUE; ! 1577: OleUIDrawHandles((LPRECT)&rcObj, hDC, dwFlags, nHandleSize, ! 1578: TRUE); ! 1579: InvertDiffRect(lprcPix, (LPRECT)&rcObj, hDC); ! 1580: } ! 1581: } else { ! 1582: if (lpLine->m_fSelected) { ! 1583: lpLine->m_fSelected = FALSE; ! 1584: OleUIDrawHandles((LPRECT)&rcObj, hDC, dwFlags, nHandleSize, ! 1585: FALSE); ! 1586: InvertDiffRect(lprcPix, (LPRECT)&rcObj, hDC); ! 1587: } ! 1588: } ! 1589: } else if (itemAction & ODA_DRAWENTIRE) { ! 1590: lpLine->m_fSelected=((itemState & ODS_SELECTED) ? TRUE : FALSE); ! 1591: if (lpLine->m_fSelected) { ! 1592: OleUIDrawHandles((LPRECT)&rcObj, hDC, dwFlags, nHandleSize, TRUE); ! 1593: InvertDiffRect(lprcPix, (LPRECT)&rcObj, hDC); ! 1594: } else { ! 1595: OleUIDrawHandles((LPRECT)&rcObj, hDC, dwFlags, nHandleSize, ! 1596: FALSE); ! 1597: InvertDiffRect(lprcPix, (LPRECT)&rcObj, hDC); ! 1598: } ! 1599: ! 1600: } ! 1601: } ! 1602: ! 1603: /* InvertDiffRect ! 1604: ** -------------- ! 1605: ** ! 1606: ** Paint the surrounding of the Obj rect black but within lprcPix ! 1607: ** (similar to the lprcPix minus lprcObj) ! 1608: */ ! 1609: static void InvertDiffRect(LPRECT lprcPix, LPRECT lprcObj, HDC hDC) ! 1610: { ! 1611: RECT rcBlack; ! 1612: ! 1613: // draw black in all space outside of object's rectangle ! 1614: rcBlack.top = lprcPix->top; ! 1615: rcBlack.bottom = lprcPix->bottom; ! 1616: ! 1617: rcBlack.left = lprcPix->left + 1; ! 1618: rcBlack.right = lprcObj->left - 1; ! 1619: InvertRect(hDC, (LPRECT)&rcBlack); ! 1620: ! 1621: rcBlack.left = lprcObj->right + 1; ! 1622: rcBlack.right = lprcPix->right - 1; ! 1623: InvertRect(hDC, (LPRECT)&rcBlack); ! 1624: ! 1625: rcBlack.top = lprcPix->top; ! 1626: rcBlack.bottom = lprcPix->top + 1; ! 1627: rcBlack.left = lprcObj->left - 1; ! 1628: rcBlack.right = lprcObj->right + 1; ! 1629: InvertRect(hDC, (LPRECT)&rcBlack); ! 1630: ! 1631: rcBlack.top = lprcPix->bottom; ! 1632: rcBlack.bottom = lprcPix->bottom - 1; ! 1633: rcBlack.left = lprcObj->left - 1; ! 1634: rcBlack.right = lprcObj->right + 1; ! 1635: InvertRect(hDC, (LPRECT)&rcBlack); ! 1636: } ! 1637: ! 1638: ! 1639: /* Edit the ContainerLine line object. ! 1640: ** returns TRUE if line was changed ! 1641: ** FALSE if the line was NOT changed ! 1642: */ ! 1643: BOOL ContainerLine_Edit(LPCONTAINERLINE lpContainerLine, HWND hWndDoc,HDC hDC) ! 1644: { ! 1645: ContainerLine_DoVerb(lpContainerLine, OLEIVERB_PRIMARY, TRUE, TRUE); ! 1646: ! 1647: /* assume object was NOT changed, if it was obj will send Changed ! 1648: ** or Saved notification. ! 1649: */ ! 1650: return FALSE; ! 1651: } ! 1652: ! 1653: ! 1654: ! 1655: /* ContainerLine_SetHeightInHimetric ! 1656: ** --------------------------------- ! 1657: ** ! 1658: ** Set the height of a ContainerLine object. The widht will be changed ! 1659: ** to keep the aspect ratio ! 1660: */ ! 1661: void ContainerLine_SetHeightInHimetric(LPCONTAINERLINE lpContainerLine, int nHeight) ! 1662: { ! 1663: LPLINE lpLine = (LPLINE)lpContainerLine; ! 1664: SIZEL sizelOleObject; ! 1665: HRESULT hrErr; ! 1666: ! 1667: if (!lpContainerLine) ! 1668: return; ! 1669: ! 1670: if (nHeight != -1) { ! 1671: ! 1672: /* if object is not already loaded, then load it now. objects are ! 1673: ** loaded lazily in this manner. ! 1674: */ ! 1675: if (! lpContainerLine->m_lpOleObj) ! 1676: ContainerLine_LoadOleObject(lpContainerLine); ! 1677: ! 1678: sizelOleObject.cy = nHeight - XformHeightInPixelsToHimetric(NULL, ! 1679: LINE_BOUNDARY_WIDTH * 2); ! 1680: ! 1681: sizelOleObject.cx = (int)(sizelOleObject.cy * ! 1682: lpContainerLine->m_sizeInHimetric.cx / ! 1683: lpContainerLine->m_sizeInHimetric.cy); ! 1684: ! 1685: hrErr = lpContainerLine->m_lpOleObj->lpVtbl->SetExtent( ! 1686: lpContainerLine->m_lpOleObj, ! 1687: lpContainerLine->m_dwDrawAspect, ! 1688: (LPSIZEL)&sizelOleObject); ! 1689: ! 1690: OleDbgOutHResult("IOleObj::SetExtent returned",hrErr); ! 1691: ! 1692: if (hrErr == NOERROR) { ! 1693: /***************************************************************** ! 1694: ** OLE Object accepts size changes, update the extents in the ** ! 1695: ** ContainerLine and Line ** ! 1696: *****************************************************************/ ! 1697: ContainerLine_UpdateExtent(lpContainerLine, ! 1698: (LPSIZEL)&sizelOleObject); ! 1699: } ! 1700: else { ! 1701: /***************************************************************** ! 1702: ** OLE Object refuses size changes, change extents of Line only ** ! 1703: *****************************************************************/ ! 1704: ContainerLine_CalcExtents(lpContainerLine, ! 1705: (LPSIZEL)&sizelOleObject); ! 1706: } ! 1707: } ! 1708: else { ! 1709: /***************************************************************** ! 1710: ** Use default OLE Object size ** ! 1711: *****************************************************************/ ! 1712: ContainerLine_CalcExtents( ! 1713: lpContainerLine, ! 1714: (LPSIZEL)&lpContainerLine->m_sizeInHimetric); ! 1715: } ! 1716: ! 1717: } ! 1718: ! 1719: ! 1720: /* ContainerLine_CalcExtents ! 1721: * ! 1722: * Purpose: ! 1723: * Calculate the corresponding line height from the OleObject size ! 1724: * Scale the line height to fit the limit if necessary ! 1725: * ! 1726: * Parameters: ! 1727: * lpsizelOleObject pointer to size of OLE Object ! 1728: * ! 1729: * Returns: ! 1730: * nil ! 1731: */ ! 1732: void ContainerLine_CalcExtents(LPCONTAINERLINE lpContainerLine, LPSIZEL lpsizelOleObject) ! 1733: { ! 1734: LPLINE lpLine = (LPLINE)lpContainerLine; ! 1735: ! 1736: UINT uMaxObjectHeight = XformHeightInPixelsToHimetric(NULL, ! 1737: LISTBOX_HEIGHT_LIMIT - 2 * LINE_BOUNDARY_WIDTH); ! 1738: ! 1739: if (!lpContainerLine || !lpsizelOleObject) ! 1740: return; ! 1741: ! 1742: lpLine->m_nWidthInHimetric = (int)lpsizelOleObject->cx; ! 1743: lpLine->m_nHeightInHimetric = (int)lpsizelOleObject->cy; ! 1744: ! 1745: // Rescale the object if height is greater than the limit ! 1746: if (lpLine->m_nHeightInHimetric > (UINT)uMaxObjectHeight) { ! 1747: ! 1748: lpLine->m_nWidthInHimetric = (UINT) ! 1749: ((long)lpLine->m_nWidthInHimetric * ! 1750: (long)uMaxObjectHeight / ! 1751: (long)lpLine->m_nHeightInHimetric); ! 1752: ! 1753: lpLine->m_nHeightInHimetric = uMaxObjectHeight; ! 1754: } ! 1755: ! 1756: // Add boundary space ! 1757: lpLine->m_nWidthInHimetric += ! 1758: XformWidthInPixelsToHimetric(NULL, LINE_BOUNDARY_WIDTH) * 2; ! 1759: lpLine->m_nHeightInHimetric += ! 1760: XformHeightInPixelsToHimetric(NULL, LINE_BOUNDARY_WIDTH) * 2; ! 1761: } ! 1762: ! 1763: ! 1764: /* ContainerLine_SaveToStg ! 1765: ** ----------------------- ! 1766: ** Save a given ContainerLine and associated OLE object to an IStorage*. ! 1767: */ ! 1768: BOOL ContainerLine_SaveToStg( ! 1769: LPCONTAINERLINE lpContainerLine, ! 1770: UINT uFormat, ! 1771: LPSTORAGE lpSrcStg, ! 1772: LPSTORAGE lpDestStg, ! 1773: LPSTREAM lpLLStm, ! 1774: BOOL fRemember ! 1775: ) ! 1776: { ! 1777: LPCONTAINERAPP lpContainerApp = (LPCONTAINERAPP)g_lpApp; ! 1778: HRESULT hrErr; ! 1779: BOOL fStatus; ! 1780: ULONG nWritten; ! 1781: BOOL fSameAsLoad = (lpSrcStg==lpDestStg ? TRUE : FALSE); ! 1782: CONTAINERLINERECORD objLineRecord; ! 1783: LPSTORAGE lpObjDestStg; ! 1784: LARGE_INTEGER dlibSavePos; ! 1785: LARGE_INTEGER dlibZeroOffset; ! 1786: LISet32( dlibZeroOffset, 0 ); ! 1787: ! 1788: // only save the ContainerLine (with OLE object) if format is compatible. ! 1789: if (uFormat != lpContainerApp->m_cfCntrOutl) ! 1790: return FALSE; ! 1791: ! 1792: /* save seek position before line record is written in case of error */ ! 1793: hrErr = lpLLStm->lpVtbl->Seek( ! 1794: lpLLStm, ! 1795: dlibZeroOffset, ! 1796: STREAM_SEEK_CUR, ! 1797: (ULARGE_INTEGER FAR*)&dlibSavePos ! 1798: ); ! 1799: if (hrErr != NOERROR) goto error; ! 1800: ! 1801: lstrcpy(objLineRecord.m_szStgName, lpContainerLine->m_szStgName); ! 1802: objLineRecord.m_fMonikerAssigned = lpContainerLine->m_fMonikerAssigned; ! 1803: objLineRecord.m_dwDrawAspect = lpContainerLine->m_dwDrawAspect; ! 1804: objLineRecord.m_sizeInHimetric = lpContainerLine->m_sizeInHimetric; ! 1805: objLineRecord.m_fIsLink = lpContainerLine->m_fIsLink; ! 1806: ! 1807: /* write line record */ ! 1808: hrErr = lpLLStm->lpVtbl->Write( ! 1809: lpLLStm, ! 1810: (LPVOID)&objLineRecord, ! 1811: sizeof(CONTAINERLINERECORD), ! 1812: &nWritten ! 1813: ); ! 1814: ! 1815: if (! OleDbgVerifySz(hrErr == NOERROR, ! 1816: "Could not write to LineList stream")) ! 1817: goto error; ! 1818: ! 1819: if (! lpContainerLine->m_lpOleObj) { ! 1820: ! 1821: /***************************************************************** ! 1822: ** CASE 1: object is NOT loaded. ! 1823: *****************************************************************/ ! 1824: ! 1825: if (fSameAsLoad) { ! 1826: /************************************************************* ! 1827: ** CASE 1A: we are saving to the current storage. because ! 1828: ** the object is not loaded, it is up-to-date ! 1829: ** (ie. nothing to do). ! 1830: *************************************************************/ ! 1831: ! 1832: ; ! 1833: ! 1834: } else { ! 1835: /************************************************************* ! 1836: ** CASE 1B: we are saving to a new storage. because ! 1837: ** the object is not loaded, we can simply copy the ! 1838: ** object's current storage to the new storage. ! 1839: *************************************************************/ ! 1840: ! 1841: /* if current object storage is not already open, then open it */ ! 1842: if (! lpContainerLine->m_lpStg) { ! 1843: lpContainerLine->m_lpStg = OleStdOpenChildStorage( ! 1844: lpSrcStg, ! 1845: lpContainerLine->m_szStgName, ! 1846: STGM_READWRITE ! 1847: ); ! 1848: if (! OleDbgVerifySz(lpContainerLine->m_lpStg != NULL, ! 1849: "Error opening child stg")) ! 1850: goto error; ! 1851: } ! 1852: ! 1853: /* Create a child storage inside the destination storage. */ ! 1854: lpObjDestStg = OleStdCreateChildStorage( ! 1855: lpDestStg, ! 1856: lpContainerLine->m_szStgName ! 1857: ); ! 1858: ! 1859: if (! OleDbgVerifySz(lpObjDestStg != NULL, ! 1860: "Could not create obj storage!")) ! 1861: goto error; ! 1862: ! 1863: hrErr = lpContainerLine->m_lpStg->lpVtbl->CopyTo( ! 1864: lpContainerLine->m_lpStg, ! 1865: 0, ! 1866: NULL, ! 1867: NULL, ! 1868: lpObjDestStg ! 1869: ); ! 1870: // REVIEW: should we handle error here? ! 1871: fStatus = OleStdCommitStorage(lpObjDestStg); ! 1872: ! 1873: /* if we are supposed to remember this storage as the new ! 1874: ** storage for the object, then release the old one and ! 1875: ** save the new one. else, throw away the new one. ! 1876: */ ! 1877: if (fRemember) { ! 1878: OleStdVerifyRelease( ! 1879: (LPUNKNOWN)lpContainerLine->m_lpStg, ! 1880: "Original object stg not released" ! 1881: ); ! 1882: lpContainerLine->m_lpStg = lpObjDestStg; ! 1883: } else { ! 1884: OleStdVerifyRelease( ! 1885: (LPUNKNOWN)lpObjDestStg, ! 1886: "Copied object stg not released" ! 1887: ); ! 1888: } ! 1889: } ! 1890: ! 1891: } else { ! 1892: ! 1893: /***************************************************************** ! 1894: ** CASE 2: object IS loaded. ! 1895: *****************************************************************/ ! 1896: ! 1897: if (fSameAsLoad) { ! 1898: /************************************************************* ! 1899: ** CASE 2A: we are saving to the current storage. if the object ! 1900: ** is not dirty, then the current storage is up-to-date ! 1901: ** (ie. nothing to do). ! 1902: *************************************************************/ ! 1903: ! 1904: LPPERSISTSTORAGE lpPersistStg; ! 1905: ! 1906: if (! lpContainerLine->m_lpPersistStg) { ! 1907: lpContainerLine->m_lpPersistStg = ! 1908: (LPPERSISTSTORAGE)OleStdQueryInterface( ! 1909: (LPUNKNOWN)lpContainerLine->m_lpOleObj, ! 1910: &IID_IPersistStorage); ! 1911: } ! 1912: ! 1913: lpPersistStg = lpContainerLine->m_lpPersistStg; ! 1914: OleDbgAssertSz( ! 1915: lpPersistStg!=NULL,"IPersistStorage NOT supported"); ! 1916: ! 1917: if (! lpPersistStg) ! 1918: goto error; ! 1919: ! 1920: hrErr = lpPersistStg->lpVtbl->IsDirty(lpPersistStg); ! 1921: ! 1922: if (hrErr != NOERROR) { ! 1923: return TRUE; /* OLE object is NOT dirty */ ! 1924: } else { ! 1925: /* OLE object IS dirty */ ! 1926: hrErr = ContainerLine_SaveOleObject( ! 1927: lpContainerLine, ! 1928: lpContainerLine->m_lpStg, ! 1929: fSameAsLoad, ! 1930: fRemember, ! 1931: TRUE /* fForceUpdate */ ! 1932: ); ! 1933: ! 1934: return ((hrErr == NOERROR) ? TRUE : FALSE); ! 1935: } ! 1936: ! 1937: } else { ! 1938: /************************************************************* ! 1939: ** CASE 2B: we are saving to a new storage. we must ! 1940: ** tell the object to save into the new storage. ! 1941: *************************************************************/ ! 1942: ! 1943: /* Create a child storage inside the destination storage. */ ! 1944: lpObjDestStg = OleStdCreateChildStorage( ! 1945: lpDestStg, ! 1946: lpContainerLine->m_szStgName ! 1947: ); ! 1948: ! 1949: if (! OleDbgVerifySz(lpObjDestStg != NULL, ! 1950: "Could not create object storage!")) { ! 1951: goto error; ! 1952: } ! 1953: ! 1954: hrErr = ContainerLine_SaveOleObject( ! 1955: lpContainerLine, ! 1956: lpObjDestStg, ! 1957: fSameAsLoad, ! 1958: fRemember, ! 1959: TRUE /* fForceUpdate */ ! 1960: ); ! 1961: ! 1962: if (hrErr != NOERROR) ! 1963: goto error; ! 1964: ! 1965: /* if we are supposed to remember this storage as the new ! 1966: ** storage for the object, then release the old one and ! 1967: ** save the new one. else, throw away the new one. ! 1968: */ ! 1969: if (fRemember) { ! 1970: OleStdVerifyRelease( ! 1971: (LPUNKNOWN)lpContainerLine->m_lpStg, ! 1972: "Original object stg not released" ! 1973: ); ! 1974: lpContainerLine->m_lpStg = lpObjDestStg; ! 1975: } else { ! 1976: OleStdVerifyRelease( ! 1977: (LPUNKNOWN)lpObjDestStg, ! 1978: "Copied object stg not released" ! 1979: ); ! 1980: } ! 1981: } ! 1982: return TRUE; ! 1983: } ! 1984: ! 1985: return TRUE; ! 1986: ! 1987: error: ! 1988: ! 1989: /* retore seek position prior to writing Line record */ ! 1990: lpLLStm->lpVtbl->Seek( ! 1991: lpLLStm, ! 1992: dlibSavePos, ! 1993: STREAM_SEEK_SET, ! 1994: NULL ! 1995: ); ! 1996: ! 1997: return FALSE; ! 1998: } ! 1999: ! 2000: ! 2001: /* ContainerLine_SaveOleObject ! 2002: ** --------------------------- ! 2003: ** Save the OLE object associated with the ContainerLine. ! 2004: ** ! 2005: ** OLE2NOTE: this function demonstrates the most basic form of ! 2006: ** saving an OLE object. see the OLE 2.0 documentation for a ! 2007: ** discussion of other more advanced strategies for saving (eg. ! 2008: ** saving with backup file and low memory save). ! 2009: */ ! 2010: HRESULT ContainerLine_SaveOleObject( ! 2011: LPCONTAINERLINE lpContainerLine, ! 2012: LPSTORAGE lpStg, ! 2013: BOOL fSameAsLoad, ! 2014: BOOL fRemember, ! 2015: BOOL fForceUpdate ! 2016: ) ! 2017: { ! 2018: LPPERSISTSTORAGE lpPersistStg; ! 2019: SCODE sc = S_OK; ! 2020: HRESULT hrErr; ! 2021: ! 2022: if (! lpContainerLine->m_lpPersistStg) { ! 2023: lpContainerLine->m_lpPersistStg = ! 2024: (LPPERSISTSTORAGE)OleStdQueryInterface( ! 2025: (LPUNKNOWN)lpContainerLine->m_lpOleObj, &IID_IPersistStorage); ! 2026: if (! lpContainerLine->m_lpPersistStg) { ! 2027: OleDbgAssert(lpContainerLine->m_lpPersistStg); ! 2028: return ResultFromScode(E_FAIL); ! 2029: } ! 2030: } ! 2031: ! 2032: lpPersistStg = lpContainerLine->m_lpPersistStg; ! 2033: ! 2034: /* OLE2NOTE: the container should NOT call IOleObject::Update ! 2035: ** before calling OleSave on an embedded object. an earlier ! 2036: ** version of the Outline sample incorrectly called ! 2037: ** IOleObject::Update here in order to guarantee that we get the ! 2038: ** latest presentation of the object when it has a coarse update ! 2039: ** granularity (eg. OLE 1.0 embeddings). it is the ! 2040: ** responsibility of the Object application to send an ! 2041: ** OnDataChange when IPersistStorage::Save is called if there ! 2042: ** currently are un-broadcast change notifications BEFORE ! 2043: ** returning from IPersistStorage::Save. these data change ! 2044: ** notifications will get through and cause the cache to be ! 2045: ** updated prior to the saving of the cache. (this discussion is ! 2046: ** only pertinent to EXE based servers that use OLE's ! 2047: ** DefHandler. calling IOleObject::Update would have the ! 2048: ** undesireable side-effect of causing any nested manual links ! 2049: ** to be updated automatically. ! 2050: */ ! 2051: ! 2052: OLEDBG_BEGIN2("OleSave called\r\n") ! 2053: hrErr = OleSave(lpPersistStg, lpStg, fSameAsLoad); ! 2054: OLEDBG_END2 ! 2055: ! 2056: // OLE2NOTE: if OleSave returns an error, you must still call ! 2057: // SaveCompleted. ! 2058: if (hrErr != NOERROR) { ! 2059: OleDbgOutHResult("WARNING: OleSave returned", hrErr); ! 2060: sc = GetScode(hrErr); ! 2061: } ! 2062: ! 2063: /* OLE2NOTE: a root level container should immediately ! 2064: ** call IPersistStorage::SaveCompleted after calling OleSave. a ! 2065: ** nested level container should not call SaveCompleted now, but ! 2066: ** must wait until SaveCompleted is call on it by its container. ! 2067: ** since our container is not a container/server, then we always ! 2068: ** call SaveComplete here. ! 2069: ** ! 2070: ** if this is a SaveAs operation, then we need to pass the lpStg ! 2071: ** back in SaveCompleted to inform the object of its new storage ! 2072: ** that it may hold on to. ! 2073: ** if this is a Save or a SaveCopyAs operation, then we simply ! 2074: ** pass NULL in SaveCompleted; the object can continue to hold ! 2075: ** its current storage. if an error occurs during the OleSave ! 2076: ** call we must still call SaveCompleted but we must pass NULL. ! 2077: */ ! 2078: OLEDBG_BEGIN2("IPersistStorage::SaveCompleted called\r\n") ! 2079: hrErr = lpPersistStg->lpVtbl->SaveCompleted( ! 2080: lpPersistStg, ! 2081: ((FAILED(sc) || !fRemember || fSameAsLoad) ? NULL : lpStg) ! 2082: ); ! 2083: OLEDBG_END2 ! 2084: ! 2085: if (hrErr != NOERROR) { ! 2086: OleDbgOutHResult("WARNING: SaveCompleted returned",hrErr); ! 2087: if (sc == S_OK) ! 2088: sc = GetScode(hrErr); ! 2089: } ! 2090: ! 2091: return ResultFromScode(sc); ! 2092: } ! 2093: ! 2094: ! 2095: /* ContainerLine_LoadFromStg ! 2096: ** ------------------------- ! 2097: ** Create a ContainerLine object and initialize it with data that ! 2098: ** was previously writen to an IStorage*. this function does not ! 2099: ** immediately OleLoad the associated OLE object, only the data of ! 2100: ** the ContainerLine object itself is loaded from the IStorage*. ! 2101: */ ! 2102: LPLINE ContainerLine_LoadFromStg( ! 2103: LPSTORAGE lpSrcStg, ! 2104: LPSTREAM lpLLStm, ! 2105: LPOUTLINEDOC lpDestDoc ! 2106: ) ! 2107: { ! 2108: HDC hDC; ! 2109: LPLINELIST lpDestLL = &lpDestDoc->m_LineList; ! 2110: ULONG nRead; ! 2111: HRESULT hrErr; ! 2112: LPCONTAINERLINE lpContainerLine; ! 2113: CONTAINERLINERECORD objLineRecord; ! 2114: ! 2115: lpContainerLine=(LPCONTAINERLINE) New((DWORD)sizeof(CONTAINERLINE)); ! 2116: if (lpContainerLine == NULL) { ! 2117: OleDbgAssertSz( ! 2118: lpContainerLine!=NULL, "Error allocating ContainerLine"); ! 2119: return NULL; ! 2120: } ! 2121: ! 2122: hDC = LineList_GetDC(lpDestLL); ! 2123: ContainerLine_Init(lpContainerLine, 0, hDC); ! 2124: LineList_ReleaseDC(lpDestLL, hDC); ! 2125: ! 2126: /* OLE2NOTE: In order to have a stable ContainerLine object we must ! 2127: ** AddRef the object's refcnt. this will be later released when ! 2128: ** the ContainerLine is deleted. ! 2129: */ ! 2130: ContainerLine_AddRef(lpContainerLine); ! 2131: ! 2132: lpContainerLine->m_lpDoc = (LPCONTAINERDOC) lpDestDoc; ! 2133: ! 2134: /* read line record */ ! 2135: hrErr = lpLLStm->lpVtbl->Read( ! 2136: lpLLStm, ! 2137: (LPVOID)&objLineRecord, ! 2138: sizeof(CONTAINERLINERECORD), ! 2139: &nRead ! 2140: ); ! 2141: ! 2142: if (!OleDbgVerifySz(hrErr==NOERROR,"Could not read from LineList stream")) ! 2143: goto error; ! 2144: ! 2145: lstrcpy(lpContainerLine->m_szStgName, objLineRecord.m_szStgName); ! 2146: lpContainerLine->m_fMonikerAssigned = objLineRecord.m_fMonikerAssigned; ! 2147: lpContainerLine->m_dwDrawAspect = objLineRecord.m_dwDrawAspect; ! 2148: lpContainerLine->m_sizeInHimetric = objLineRecord.m_sizeInHimetric; ! 2149: lpContainerLine->m_fIsLink = objLineRecord.m_fIsLink; ! 2150: ! 2151: return (LPLINE)lpContainerLine; ! 2152: ! 2153: error: ! 2154: // destroy partially created ContainerLine ! 2155: if (lpContainerLine) ! 2156: ContainerLine_Delete(lpContainerLine); ! 2157: return NULL; ! 2158: } ! 2159: ! 2160: ! 2161: /* ContainerLine_GetRelMoniker ! 2162: ** --------------------------- ! 2163: ** Retrieve the relative item moniker which identifies the OLE object ! 2164: ** relative to the container document. ! 2165: ** ! 2166: ** Returns NULL if a moniker can NOT be created. ! 2167: */ ! 2168: LPMONIKER ContainerLine_GetRelMoniker( ! 2169: LPCONTAINERLINE lpContainerLine, ! 2170: DWORD dwAssign ! 2171: ) ! 2172: { ! 2173: LPMONIKER lpmk = NULL; ! 2174: ! 2175: /* OLE2NOTE: we should only give out a moniker for the OLE object ! 2176: ** if the object is allowed to be linked to from the inside. if ! 2177: ** so we are allowed to give out a moniker which binds to the ! 2178: ** running OLE object). if the object is an OLE 2.0 embedded ! 2179: ** object then it is allowed to be linked to from the inside. if ! 2180: ** the object is either an OleLink or an OLE 1.0 embedding ! 2181: ** then it can not be linked to from the inside. ! 2182: ** if we were a container/server app then we could offer linking ! 2183: ** to the outside of the object (ie. a pseudo object within our ! 2184: ** document). we are a container only app that does not support ! 2185: ** linking to ranges of its data. ! 2186: */ ! 2187: ! 2188: switch (dwAssign) { ! 2189: ! 2190: case GETMONIKER_FORCEASSIGN: ! 2191: ! 2192: /* Force the assignment of the name. This is called when a ! 2193: ** Paste Link actually occurs. From now on we want ! 2194: ** to inform the OLE object that its moniker is ! 2195: ** assigned and is thus necessary to register itself ! 2196: ** in the RunningObjectTable. ! 2197: */ ! 2198: CreateItemMoniker( ! 2199: OLESTDDELIM, ! 2200: lpContainerLine->m_szStgName, ! 2201: &lpmk ! 2202: ); ! 2203: ! 2204: /* OLE2NOTE: if the OLE object is already loaded and it ! 2205: ** is being assigned a moniker for the first time, ! 2206: ** then we need to inform it that it now has a moniker ! 2207: ** assigned by calling IOleObject::SetMoniker. this ! 2208: ** will force the OLE object to register in the ! 2209: ** RunningObjectTable when it enters the running ! 2210: ** state. if the object is not currently loaded, ! 2211: ** SetMoniker will be called automatically later when ! 2212: ** the object is loaded by the function ! 2213: ** ContainerLine_LoadOleObject. ! 2214: */ ! 2215: if (lpContainerLine->m_lpOleObj && ! 2216: !lpContainerLine->m_fMonikerAssigned) { ! 2217: OLEDBG_BEGIN2("IOleObject::SetMoniker called\r\n") ! 2218: lpContainerLine->m_lpOleObj->lpVtbl->SetMoniker( ! 2219: lpContainerLine->m_lpOleObj, ! 2220: OLEWHICHMK_OBJREL, ! 2221: lpmk ! 2222: ); ! 2223: OLEDBG_END2 ! 2224: } ! 2225: ! 2226: /* we must remember forever more that this object has a ! 2227: ** moniker assigned. ! 2228: */ ! 2229: lpContainerLine->m_fMonikerAssigned = TRUE; ! 2230: break; ! 2231: ! 2232: case GETMONIKER_ONLYIFTHERE: ! 2233: ! 2234: /* If the OLE object currently has a moniker assigned, ! 2235: ** then return it. ! 2236: */ ! 2237: if (lpContainerLine->m_fMonikerAssigned) { ! 2238: CreateItemMoniker( ! 2239: OLESTDDELIM, ! 2240: lpContainerLine->m_szStgName, ! 2241: &lpmk ! 2242: ); ! 2243: } ! 2244: break; ! 2245: ! 2246: case GETMONIKER_TEMPFORUSER: ! 2247: ! 2248: /* Return the moniker that would be used for the OLE ! 2249: ** object but do NOT force moniker assignment at ! 2250: ** this point. Since our strategy is to use the ! 2251: ** storage name of the object as its item name, we ! 2252: ** can simply create the corresponding ItemMoniker ! 2253: ** (indepenedent of whether the moniker is currently ! 2254: ** assigned or not). ! 2255: */ ! 2256: CreateItemMoniker( ! 2257: OLESTDDELIM, ! 2258: lpContainerLine->m_szStgName, ! 2259: &lpmk ! 2260: ); ! 2261: break; ! 2262: ! 2263: case GETMONIKER_UNASSIGN: ! 2264: ! 2265: lpContainerLine->m_fMonikerAssigned = FALSE; ! 2266: break; ! 2267: ! 2268: } ! 2269: ! 2270: return lpmk; ! 2271: } ! 2272: ! 2273: ! 2274: /* ContainerLine_GetFullMoniker ! 2275: ** ---------------------------- ! 2276: ** Retrieve the full absolute moniker which identifies the OLE object ! 2277: ** in the container document. ! 2278: ** this moniker is created as a composite of the absolute moniker for ! 2279: ** the entire document appended with an item moniker which identifies ! 2280: ** the OLE object relative to the document. ! 2281: ** Returns NULL if a moniker can NOT be created. ! 2282: */ ! 2283: LPMONIKER ContainerLine_GetFullMoniker( ! 2284: LPCONTAINERLINE lpContainerLine, ! 2285: DWORD dwAssign ! 2286: ) ! 2287: { ! 2288: LPMONIKER lpmkDoc = NULL; ! 2289: LPMONIKER lpmkItem = NULL; ! 2290: LPMONIKER lpmkFull = NULL; ! 2291: ! 2292: lpmkDoc = OleDoc_GetFullMoniker( ! 2293: (LPOLEDOC)lpContainerLine->m_lpDoc, ! 2294: dwAssign ! 2295: ); ! 2296: if (! lpmkDoc) return NULL; ! 2297: ! 2298: lpmkItem = ContainerLine_GetRelMoniker(lpContainerLine, dwAssign); ! 2299: ! 2300: if (lpmkItem) { ! 2301: CreateGenericComposite(lpmkDoc, lpmkItem, (LPMONIKER FAR*)&lpmkFull); ! 2302: OleStdRelease((LPUNKNOWN)lpmkItem); ! 2303: } ! 2304: ! 2305: if (lpmkDoc) ! 2306: OleStdRelease((LPUNKNOWN)lpmkDoc); ! 2307: ! 2308: return lpmkFull; ! 2309: } ! 2310: ! 2311: ! 2312: /* ContainerLine_GetTextLen ! 2313: * ------------------------ ! 2314: * ! 2315: * Return length of the string representation of the ContainerLine ! 2316: * (not considering the tab level). we will use the following as the ! 2317: * string representation of a ContainerLine: ! 2318: * "<" + user type name of OLE object + ">" ! 2319: * eg: ! 2320: * <Microsoft Excel Worksheet> ! 2321: */ ! 2322: int ContainerLine_GetTextLen(LPCONTAINERLINE lpContainerLine) ! 2323: { ! 2324: LPSTR lpszUserType = NULL; ! 2325: HRESULT hrErr; ! 2326: int nLen; ! 2327: BOOL fIsLink = ContainerLine_IsOleLink(lpContainerLine); ! 2328: ! 2329: /* if object is not already loaded, then load it now. objects are ! 2330: ** loaded lazily in this manner. ! 2331: */ ! 2332: if (! lpContainerLine->m_lpOleObj) ! 2333: ContainerLine_LoadOleObject(lpContainerLine); ! 2334: ! 2335: OLEDBG_BEGIN2("IOleObject::GetUserType called\r\n") ! 2336: hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetUserType( ! 2337: lpContainerLine->m_lpOleObj, ! 2338: USERCLASSTYPE_FULL, ! 2339: &lpszUserType ! 2340: ); ! 2341: OLEDBG_END2 ! 2342: ! 2343: if (hrErr != NOERROR) { ! 2344: // user type is NOT available ! 2345: nLen = sizeof(UNKNOWN_OLEOBJ_TYPE) + 2; // allow space for '<' + '>' ! 2346: nLen += lstrlen((LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT)) + 1; ! 2347: } else { ! 2348: nLen = lstrlen(lpszUserType) + 2; // allow space for '<' + '>' ! 2349: nLen += lstrlen((LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT)) + 1; ! 2350: ! 2351: /* OLE2NOTE: we must free the string that was allocated by the ! 2352: ** IOleObject::GetUserType method. ! 2353: */ ! 2354: OleStdFreeString(lpszUserType, NULL); ! 2355: } ! 2356: ! 2357: return nLen; ! 2358: } ! 2359: ! 2360: ! 2361: /* ContainerLine_GetTextData ! 2362: * ------------------------- ! 2363: * ! 2364: * Return the string representation of the ContainerLine ! 2365: * (not considering the tab level). we will use the following as the ! 2366: * string representation of a ContainerLine: ! 2367: * "<" + user type name of OLE object + ">" ! 2368: * eg: ! 2369: * <Microsoft Excel Worksheet> ! 2370: */ ! 2371: void ContainerLine_GetTextData(LPCONTAINERLINE lpContainerLine, LPSTR lpszBuf) ! 2372: { ! 2373: LPSTR lpszUserType = NULL; ! 2374: BOOL fIsLink = ContainerLine_IsOleLink(lpContainerLine); ! 2375: HRESULT hrErr; ! 2376: ! 2377: /* if object is not already loaded, then load it now. objects are ! 2378: ** loaded lazily in this manner. ! 2379: */ ! 2380: if (! lpContainerLine->m_lpOleObj) ! 2381: ContainerLine_LoadOleObject(lpContainerLine); ! 2382: ! 2383: hrErr = lpContainerLine->m_lpOleObj->lpVtbl->GetUserType( ! 2384: lpContainerLine->m_lpOleObj, ! 2385: USERCLASSTYPE_FULL, ! 2386: &lpszUserType ! 2387: ); ! 2388: ! 2389: if (hrErr != NOERROR) { ! 2390: // user type is NOT available ! 2391: wsprintf( ! 2392: lpszBuf, ! 2393: "<%s %s>", ! 2394: UNKNOWN_OLEOBJ_TYPE, ! 2395: (LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT) ! 2396: ); ! 2397: } else { ! 2398: wsprintf( ! 2399: lpszBuf, ! 2400: "<%s %s>", ! 2401: lpszUserType, ! 2402: (LPSTR)(fIsLink ? szOLELINK : szOLEOBJECT) ! 2403: ); ! 2404: ! 2405: /* OLE2NOTE: we must free the string that was allocated by the ! 2406: ** IOleObject::GetUserType method. ! 2407: */ ! 2408: OleStdFreeString(lpszUserType, NULL); ! 2409: } ! 2410: } ! 2411: ! 2412: ! 2413: /* ContainerLine_GetOutlineData ! 2414: * ---------------------------- ! 2415: * ! 2416: * Return the CF_OUTLINE format data for the ContainerLine. ! 2417: */ ! 2418: BOOL ContainerLine_GetOutlineData( ! 2419: LPCONTAINERLINE lpContainerLine, ! 2420: LPTEXTLINE lpBuf ! 2421: ) ! 2422: { ! 2423: LPLINE lpLine = (LPLINE)lpContainerLine; ! 2424: LPLINELIST lpLL = &((LPOUTLINEDOC)lpContainerLine->m_lpDoc)->m_LineList; ! 2425: HDC hDC; ! 2426: char szTmpBuf[MAXSTRLEN+1]; ! 2427: LPTEXTLINE lpTmpTextLine; ! 2428: ! 2429: // Create a TextLine with the Text representation of the ContainerLine. ! 2430: ContainerLine_GetTextData(lpContainerLine, (LPSTR)szTmpBuf); ! 2431: ! 2432: hDC = LineList_GetDC(lpLL); ! 2433: lpTmpTextLine = TextLine_Create(hDC, lpLine->m_nTabLevel, szTmpBuf); ! 2434: LineList_ReleaseDC(lpLL, hDC); ! 2435: ! 2436: TextLine_Copy(lpTmpTextLine, lpBuf); ! 2437: ! 2438: // Delete the temporary TextLine ! 2439: TextLine_Delete(lpTmpTextLine); ! 2440: return TRUE; ! 2441: } ! 2442: ! 2443: ! 2444: /* ContainerLine_GetOleObjectRectInPixels ! 2445: ** -------------------------------------- ! 2446: ** Get the extent of the OLE Object contained in the given Line in ! 2447: ** client coordinates after scaling. ! 2448: */ ! 2449: void ContainerLine_GetOleObjectRectInPixels(LPCONTAINERLINE lpContainerLine, LPRECT lprc) ! 2450: { ! 2451: LPOUTLINEDOC lpOutlineDoc; ! 2452: LPSCALEFACTOR lpscale; ! 2453: LPLINELIST lpLL; ! 2454: LPLINE lpLine; ! 2455: int nIndex; ! 2456: HDC hdcLL; ! 2457: ! 2458: if (!lpContainerLine || !lprc) ! 2459: return; ! 2460: ! 2461: lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; ! 2462: lpscale = OutlineDoc_GetScaleFactor(lpOutlineDoc); ! 2463: lpLL = OutlineDoc_GetLineList(lpOutlineDoc); ! 2464: lpLine = (LPLINE)lpContainerLine; ! 2465: nIndex = LineList_GetLineIndex(lpLL, lpLine); ! 2466: ! 2467: LineList_GetLineRect(lpLL, nIndex, lprc); ! 2468: ! 2469: hdcLL = GetDC(lpLL->m_hWndListBox); ! 2470: ! 2471: /* lprc is set to be size of Line Object (including the boundary) */ ! 2472: lprc->left += (int)( ! 2473: (long)XformWidthInHimetricToPixels(hdcLL, ! 2474: lpLine->m_nTabWidthInHimetric + ! 2475: LOWORD(OutlineDoc_GetMargin(lpOutlineDoc))) * ! 2476: lpscale->dwSxN / lpscale->dwSxD); ! 2477: lprc->right = (int)( ! 2478: lprc->left + (long) ! 2479: XformWidthInHimetricToPixels(hdcLL, lpLine->m_nWidthInHimetric) * ! 2480: lpscale->dwSxN / lpscale->dwSxD); ! 2481: ! 2482: // Remove the boundary from rect ! 2483: InflateRect( ! 2484: lprc, ! 2485: (int)(-LINE_BOUNDARY_WIDTH * lpscale->dwSxN / lpscale->dwSxD), ! 2486: (int)(-LINE_BOUNDARY_WIDTH * lpscale->dwSyN / lpscale->dwSyD) ! 2487: ); ! 2488: ! 2489: ReleaseDC(lpLL->m_hWndListBox, hdcLL); ! 2490: } ! 2491: ! 2492: ! 2493: /* ContainerLine_GetOleObjectSizeInHimetric ! 2494: ** ---------------------------------------- ! 2495: ** Get the size of the OLE Object contained in the given Line ! 2496: */ ! 2497: void ContainerLine_GetOleObjectSizeInHimetric(LPCONTAINERLINE lpContainerLine, LPSIZEL lpsizel) ! 2498: { ! 2499: if (!lpContainerLine || !lpsizel) ! 2500: return; ! 2501: ! 2502: *lpsizel = lpContainerLine->m_sizeInHimetric; ! 2503: } ! 2504: ! 2505: ! 2506: ! 2507: /************************************************************************* ! 2508: ** ContainerLine::IUnknown interface implementation ! 2509: *************************************************************************/ ! 2510: ! 2511: STDMETHODIMP CntrLine_Unk_QueryInterface( ! 2512: LPUNKNOWN lpThis, ! 2513: REFIID riid, ! 2514: LPVOID FAR* lplpvObj ! 2515: ) ! 2516: { ! 2517: LPCONTAINERLINE lpContainerLine = ! 2518: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2519: ! 2520: return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj); ! 2521: } ! 2522: ! 2523: ! 2524: STDMETHODIMP_(ULONG) CntrLine_Unk_AddRef(LPUNKNOWN lpThis) ! 2525: { ! 2526: LPCONTAINERLINE lpContainerLine = ! 2527: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2528: ! 2529: OleDbgAddRefMethod(lpThis, "IUnknown"); ! 2530: ! 2531: return ContainerLine_AddRef(lpContainerLine); ! 2532: } ! 2533: ! 2534: ! 2535: STDMETHODIMP_(ULONG) CntrLine_Unk_Release(LPUNKNOWN lpThis) ! 2536: { ! 2537: LPCONTAINERLINE lpContainerLine = ! 2538: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2539: ! 2540: OleDbgReleaseMethod(lpThis, "IUnknown"); ! 2541: ! 2542: return ContainerLine_Release(lpContainerLine); ! 2543: } ! 2544: ! 2545: ! 2546: /************************************************************************* ! 2547: ** ContainerLine::IOleClientSite interface implementation ! 2548: *************************************************************************/ ! 2549: ! 2550: STDMETHODIMP CntrLine_CliSite_QueryInterface( ! 2551: LPOLECLIENTSITE lpThis, ! 2552: REFIID riid, ! 2553: LPVOID FAR* lplpvObj ! 2554: ) ! 2555: { ! 2556: LPCONTAINERLINE lpContainerLine = ! 2557: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2558: ! 2559: return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj); ! 2560: } ! 2561: ! 2562: ! 2563: STDMETHODIMP_(ULONG) CntrLine_CliSite_AddRef(LPOLECLIENTSITE lpThis) ! 2564: { ! 2565: LPCONTAINERLINE lpContainerLine = ! 2566: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2567: ! 2568: OleDbgAddRefMethod(lpThis, "IOleClientSite"); ! 2569: ! 2570: return ContainerLine_AddRef(lpContainerLine); ! 2571: } ! 2572: ! 2573: ! 2574: STDMETHODIMP_(ULONG) CntrLine_CliSite_Release(LPOLECLIENTSITE lpThis) ! 2575: { ! 2576: LPCONTAINERLINE lpContainerLine = ! 2577: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2578: ! 2579: OleDbgReleaseMethod(lpThis, "IOleClientSite"); ! 2580: ! 2581: return ContainerLine_Release(lpContainerLine); ! 2582: } ! 2583: ! 2584: ! 2585: STDMETHODIMP CntrLine_CliSite_SaveObject(LPOLECLIENTSITE lpThis) ! 2586: { ! 2587: LPCONTAINERLINE lpContainerLine = ! 2588: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2589: SCODE sc = E_FAIL; ! 2590: HRESULT hrErr; ! 2591: BOOL fSameAsLoad = TRUE; ! 2592: BOOL fRemember = TRUE; ! 2593: ! 2594: OLEDBG_BEGIN2("CntrLine_CliSite_SaveObject\r\n") ! 2595: ! 2596: if (lpContainerLine->m_lpOleObj == NULL) { ! 2597: OleDbgAssertSz( ! 2598: lpContainerLine->m_lpOleObj != NULL, "OLE object not loaded"); ! 2599: sc = E_FAIL; ! 2600: goto error; ! 2601: } ! 2602: ! 2603: // mark ContainerDoc as now dirty ! 2604: OutlineDoc_SetModified( ! 2605: (LPOUTLINEDOC)lpContainerLine->m_lpDoc, TRUE, TRUE, FALSE); ! 2606: ! 2607: /* Tell OLE object to save itself */ ! 2608: hrErr = ContainerLine_SaveOleObject( ! 2609: lpContainerLine, ! 2610: lpContainerLine->m_lpStg, ! 2611: fSameAsLoad, ! 2612: fRemember, ! 2613: FALSE /* fForceUpdate */ ! 2614: ); ! 2615: ! 2616: if (hrErr != NOERROR) { ! 2617: sc = GetScode(hrErr); ! 2618: goto error; ! 2619: } ! 2620: ! 2621: OLEDBG_END2 ! 2622: return NOERROR; ! 2623: ! 2624: error: ! 2625: OLEDBG_END2 ! 2626: return ResultFromScode(sc); ! 2627: } ! 2628: ! 2629: ! 2630: STDMETHODIMP CntrLine_CliSite_GetMoniker( ! 2631: LPOLECLIENTSITE lpThis, ! 2632: DWORD dwAssign, ! 2633: DWORD dwWhichMoniker, ! 2634: LPMONIKER FAR* lplpmk ! 2635: ) ! 2636: { ! 2637: LPCONTAINERLINE lpContainerLine; ! 2638: ! 2639: lpContainerLine=((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2640: ! 2641: OLEDBG_BEGIN2("CntrLine_CliSite_GetMoniker\r\n") ! 2642: ! 2643: // OLE2NOTE: we must make sure to set output pointer parameters to NULL ! 2644: *lplpmk = NULL; ! 2645: ! 2646: switch (dwWhichMoniker) { ! 2647: ! 2648: case OLEWHICHMK_CONTAINER: ! 2649: /* OLE2NOTE: create a FileMoniker which identifies the ! 2650: ** entire container document. ! 2651: */ ! 2652: *lplpmk = OleDoc_GetFullMoniker( ! 2653: (LPOLEDOC)lpContainerLine->m_lpDoc, ! 2654: dwAssign ! 2655: ); ! 2656: break; ! 2657: ! 2658: case OLEWHICHMK_OBJREL: ! 2659: ! 2660: /* OLE2NOTE: create an ItemMoniker which identifies the ! 2661: ** OLE object relative to the container document. ! 2662: */ ! 2663: *lplpmk = ContainerLine_GetRelMoniker(lpContainerLine, dwAssign); ! 2664: break; ! 2665: ! 2666: case OLEWHICHMK_OBJFULL: ! 2667: { ! 2668: /* OLE2NOTE: create an absolute moniker which identifies the ! 2669: ** OLE object in the container document. this moniker is ! 2670: ** created as a composite of the absolute moniker for the ! 2671: ** entire document appended with an item moniker which ! 2672: ** identifies the OLE object relative to the document. ! 2673: */ ! 2674: ! 2675: *lplpmk = ContainerLine_GetFullMoniker(lpContainerLine, dwAssign); ! 2676: break; ! 2677: } ! 2678: } ! 2679: ! 2680: OLEDBG_END2 ! 2681: ! 2682: if (*lplpmk != NULL) ! 2683: return NOERROR; ! 2684: else ! 2685: return ResultFromScode(E_FAIL); ! 2686: } ! 2687: ! 2688: ! 2689: STDMETHODIMP CntrLine_CliSite_GetContainer( ! 2690: LPOLECLIENTSITE lpThis, ! 2691: LPOLECONTAINER FAR* lplpContainer ! 2692: ) ! 2693: { ! 2694: LPCONTAINERLINE lpContainerLine; ! 2695: HRESULT hrErr; ! 2696: ! 2697: OLEDBG_BEGIN2("CntrLine_CliSite_GetContainer\r\n") ! 2698: ! 2699: lpContainerLine=((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2700: ! 2701: hrErr = OleDoc_QueryInterface( ! 2702: (LPOLEDOC)lpContainerLine->m_lpDoc, ! 2703: &IID_IOleContainer, ! 2704: (LPVOID FAR*)lplpContainer ! 2705: ); ! 2706: ! 2707: OLEDBG_END2 ! 2708: return hrErr; ! 2709: } ! 2710: ! 2711: ! 2712: STDMETHODIMP CntrLine_CliSite_ShowObject(LPOLECLIENTSITE lpThis) ! 2713: { ! 2714: LPCONTAINERLINE lpContainerLine = ! 2715: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2716: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; ! 2717: LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); ! 2718: int nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); ! 2719: HWND hWndFrame = OutlineApp_GetFrameWindow(g_lpApp); ! 2720: ! 2721: OLEDBG_BEGIN2("CntrLine_CliSite_ShowObject\r\n") ! 2722: ! 2723: /* make sure our doc window is visible and not minimized. ! 2724: ** the OutlineDoc_ShowWindow function will cause the app window ! 2725: ** to show itself SW_SHOWNORMAL. ! 2726: */ ! 2727: if (! IsWindowVisible(hWndFrame) || IsIconic(hWndFrame)) ! 2728: OutlineDoc_ShowWindow(lpOutlineDoc); ! 2729: ! 2730: /* make sure that the OLE object is currently in view. if necessary ! 2731: ** scroll the document in order to bring it into view. ! 2732: */ ! 2733: LineList_ScrollLineIntoView(lpLL, nIndex); ! 2734: ! 2735: #if defined( INPLACE_CNTR ) ! 2736: /* after the in-place object is scrolled into view, we need to ask ! 2737: ** it to update its rect for the new clip rect coordinates ! 2738: */ ! 2739: ContainerDoc_UpdateInPlaceObjectRects((LPCONTAINERDOC)lpOutlineDoc, 0); ! 2740: #endif ! 2741: ! 2742: OLEDBG_END2 ! 2743: return NOERROR; ! 2744: } ! 2745: ! 2746: ! 2747: STDMETHODIMP CntrLine_CliSite_OnShowWindow(LPOLECLIENTSITE lpThis, BOOL fShow) ! 2748: { ! 2749: LPCONTAINERLINE lpContainerLine = ! 2750: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2751: LPOUTLINEDOC lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; ! 2752: LPLINELIST lpLL = OutlineDoc_GetLineList(lpOutlineDoc); ! 2753: int nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); ! 2754: ! 2755: if (fShow) { ! 2756: OLEDBG_BEGIN2("CntrLine_CliSite_OnShowWindow(TRUE)\r\n") ! 2757: ! 2758: /* OLE2NOTE: we need to hatch out the OLE object now; it has ! 2759: ** just been opened in a window elsewhere (open editing as ! 2760: ** opposed to in-place activation). ! 2761: ** force the line to re-draw with the hatch. ! 2762: */ ! 2763: lpContainerLine->m_fObjWinOpen = TRUE; ! 2764: LineList_ForceLineRedraw(lpLL, nIndex, FALSE); ! 2765: ! 2766: } else { ! 2767: OLEDBG_BEGIN2("CntrLine_CliSite_OnShowWindow(FALSE)\r\n") ! 2768: ! 2769: /* OLE2NOTE: the object associated with this container site has ! 2770: ** just closed its server window. we should now remove the ! 2771: ** hatching that indicates that the object is open ! 2772: ** elsewhere. also our window should now come to the top. ! 2773: ** force the line to re-draw without the hatch. ! 2774: */ ! 2775: lpContainerLine->m_fObjWinOpen = FALSE; ! 2776: LineList_ForceLineRedraw(lpLL, nIndex, TRUE); ! 2777: ! 2778: BringWindowToTop(lpOutlineDoc->m_hWndDoc); ! 2779: SetFocus(lpOutlineDoc->m_hWndDoc); ! 2780: } ! 2781: ! 2782: OLEDBG_END2 ! 2783: return NOERROR; ! 2784: } ! 2785: ! 2786: ! 2787: STDMETHODIMP CntrLine_CliSite_RequestNewObjectLayout(LPOLECLIENTSITE lpThis) ! 2788: { ! 2789: OleDbgOut2("CntrLine_CliSite_RequestNewObjectLayout\r\n"); ! 2790: ! 2791: /* OLE2NOTE: this method is NOT yet used. it is for future layout ! 2792: ** negotiation support. ! 2793: */ ! 2794: return ResultFromScode(E_NOTIMPL); ! 2795: } ! 2796: ! 2797: ! 2798: /************************************************************************* ! 2799: ** ContainerLine::IAdviseSink interface implementation ! 2800: *************************************************************************/ ! 2801: ! 2802: STDMETHODIMP CntrLine_AdvSink_QueryInterface( ! 2803: LPADVISESINK lpThis, ! 2804: REFIID riid, ! 2805: LPVOID FAR* lplpvObj ! 2806: ) ! 2807: { ! 2808: LPCONTAINERLINE lpContainerLine = ! 2809: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2810: ! 2811: return ContainerLine_QueryInterface(lpContainerLine, riid, lplpvObj); ! 2812: } ! 2813: ! 2814: ! 2815: STDMETHODIMP_(ULONG) CntrLine_AdvSink_AddRef(LPADVISESINK lpThis) ! 2816: { ! 2817: LPCONTAINERLINE lpContainerLine = ! 2818: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2819: ! 2820: OleDbgAddRefMethod(lpThis, "IAdviseSink"); ! 2821: ! 2822: return ContainerLine_AddRef(lpContainerLine); ! 2823: } ! 2824: ! 2825: ! 2826: STDMETHODIMP_(ULONG) CntrLine_AdvSink_Release (LPADVISESINK lpThis) ! 2827: { ! 2828: LPCONTAINERLINE lpContainerLine = ! 2829: ((struct COleClientSiteImpl FAR*)lpThis)->lpContainerLine; ! 2830: ! 2831: OleDbgReleaseMethod(lpThis, "IAdviseSink"); ! 2832: ! 2833: return ContainerLine_Release(lpContainerLine); ! 2834: } ! 2835: ! 2836: ! 2837: STDMETHODIMP_(void) CntrLine_AdvSink_OnDataChange( ! 2838: LPADVISESINK lpThis, ! 2839: FORMATETC FAR* lpFormatetc, ! 2840: STGMEDIUM FAR* lpStgmed ! 2841: ) ! 2842: { ! 2843: OleDbgOut2("CntrLine_AdvSink_OnDataChange\r\n"); ! 2844: ! 2845: // We are not interested in data changes (only view changes) ! 2846: // (ie. nothing to do) ! 2847: } ! 2848: ! 2849: ! 2850: STDMETHODIMP_(void) CntrLine_AdvSink_OnViewChange( ! 2851: LPADVISESINK lpThis, ! 2852: DWORD aspects, ! 2853: LONG lindex ! 2854: ) ! 2855: { ! 2856: LPCONTAINERLINE lpContainerLine; ! 2857: LPOUTLINEDOC lpOutlineDoc; ! 2858: HWND hWndDoc; ! 2859: LPLINELIST lpLL; ! 2860: MSG msg; ! 2861: int nIndex; ! 2862: ! 2863: OLEDBG_BEGIN2("CntrLine_AdvSink_OnViewChange\r\n") ! 2864: ! 2865: lpContainerLine = ((struct CAdviseSinkImpl FAR*)lpThis)->lpContainerLine; ! 2866: lpOutlineDoc = (LPOUTLINEDOC)lpContainerLine->m_lpDoc; ! 2867: ! 2868: /* OLE2NOTE: at this point we simply invalidate the rectangle of ! 2869: ** the object to force a repaint in the future, we mark ! 2870: ** that the extents of the object may have changed ! 2871: ** (m_fDoGetExtent=TRUE), and we post a message ! 2872: ** (WM_U_UPDATEOBJECTEXTENT) to our document that one or more ! 2873: ** OLE objects may need to have their extents updated. later ! 2874: ** when this message is processed, the document loops through ! 2875: ** all lines to see if any are marked as needing an extent update. ! 2876: ** if infact the extents did change. this can be done by calling ! 2877: ** IOleObject::GetExtent to retreive the object's current ! 2878: ** extents and comparing with the last known extents for the ! 2879: ** object. if the extents changed, then relayout space for the ! 2880: ** object before drawing. we postpone the check to get ! 2881: ** the extents now because OnViewChange is an asyncronis method, ! 2882: ** and we have to careful not to call any syncronis methods back ! 2883: ** to the object. it is good practise to not call any object ! 2884: ** methods from within an asyncronis notification method. ! 2885: ** if there is already WM_U_UPDATEOBJECTEXTENT message waiting ! 2886: ** in our message queue, there is no need to post another one. ! 2887: ** in this way, if the server is updating quicker than we can ! 2888: ** keep up, we do not make unneccsary GetExtent calls. also if ! 2889: ** drawing is disabled, we postpone updating the extents of any ! 2890: ** objects until drawing is re-enabled. ! 2891: */ ! 2892: lpContainerLine->m_fDoGetExtent = TRUE; ! 2893: hWndDoc = OutlineDoc_GetWindow((LPOUTLINEDOC)lpContainerLine->m_lpDoc); ! 2894: ! 2895: if (lpOutlineDoc->m_nDisableDraw == 0 && ! 2896: ! PeekMessage(&msg, hWndDoc, ! 2897: WM_U_UPDATEOBJECTEXTENT, WM_U_UPDATEOBJECTEXTENT, ! 2898: PM_NOREMOVE | PM_NOYIELD)) { ! 2899: PostMessage( ! 2900: hWndDoc, WM_U_UPDATEOBJECTEXTENT, 0, 0L); ! 2901: } ! 2902: ! 2903: // force the modified line to redraw. ! 2904: lpLL = OutlineDoc_GetLineList(lpOutlineDoc); ! 2905: nIndex = LineList_GetLineIndex(lpLL, (LPLINE)lpContainerLine); ! 2906: LineList_ForceLineRedraw(lpLL, nIndex, TRUE); ! 2907: ! 2908: // mark ContainerDoc as now dirty ! 2909: OutlineDoc_SetModified(lpOutlineDoc, TRUE, TRUE, FALSE); ! 2910: ! 2911: OLEDBG_END2 ! 2912: } ! 2913: ! 2914: ! 2915: STDMETHODIMP_(void) CntrLine_AdvSink_OnRename( ! 2916: LPADVISESINK lpThis, ! 2917: LPMONIKER lpmk ! 2918: ) ! 2919: { ! 2920: OleDbgOut2("CntrLine_AdvSink_OnRename\r\n"); ! 2921: ! 2922: /* OLE2NOTE: the Embedding Container has nothing to do here. this ! 2923: ** notification is important for linking situations. it tells ! 2924: ** the OleLink objects to update their moniker because the ! 2925: ** source object has been renamed (track the link source). ! 2926: */ ! 2927: } ! 2928: ! 2929: ! 2930: STDMETHODIMP_(void) CntrLine_AdvSink_OnSave(LPADVISESINK lpThis) ! 2931: { ! 2932: OleDbgOut2("CntrLine_AdvSink_OnSave\r\n"); ! 2933: ! 2934: /* OLE2NOTE: the Embedding Container has nothing to do here. this ! 2935: ** notification is only useful to clients which have set up a ! 2936: ** data cache with the ADVFCACHE_ONSAVE flag. ! 2937: */ ! 2938: } ! 2939: ! 2940: ! 2941: STDMETHODIMP_(void) CntrLine_AdvSink_OnClose(LPADVISESINK lpThis) ! 2942: { ! 2943: OleDbgOut2("CntrLine_AdvSink_OnClose\r\n"); ! 2944: ! 2945: /* OLE2NOTE: the Embedding Container has nothing to do here. this ! 2946: ** notification is important for the OLE's default object handler ! 2947: ** and the OleLink object. it tells them the remote object is ! 2948: ** shutting down. ! 2949: */ ! 2950: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.