Annotation of mstools/ole20/samples/outline/cntrline.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.