Annotation of mstools/ole20/samples/outline/cntrline.c, revision 1.1.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.