diff options
Diffstat (limited to 'binfilter/bf_so3/source/ole/socont.cxx')
-rw-r--r-- | binfilter/bf_so3/source/ole/socont.cxx | 2401 |
1 files changed, 2401 insertions, 0 deletions
diff --git a/binfilter/bf_so3/source/ole/socont.cxx b/binfilter/bf_so3/source/ole/socont.cxx new file mode 100644 index 000000000000..10cfbe52609c --- /dev/null +++ b/binfilter/bf_so3/source/ole/socont.cxx @@ -0,0 +1,2401 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "socont.h" +#include <bf_so3/svstor.hxx> +#include <sal/macros.h> + +#define LOMETRIC_PER_INCH 254 + +#define HIMETRIC_PER_INCH 2540 //Number HIMETRIC units per inch +#define PTS_PER_INCH 72 //Number points (font size) per inch + +#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli)) +#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH) + +namespace binfilter { + +void SO_MetricRectInPixelsToHimetric( LPRECT prcPix, LPRECT prcHiMetric) + { + int iXppli; //Pixels per logical inch along width + int iYppli; //Pixels per logical inch along height + int iXextInPix=(prcPix->right-prcPix->left); + int iYextInPix=(prcPix->bottom-prcPix->top); + BOOL fSystemDC=FALSE; + + HDC hDC = GetDC(NULL); + fSystemDC=TRUE; + + iXppli=GetDeviceCaps (hDC, LOGPIXELSX); + iYppli=GetDeviceCaps (hDC, LOGPIXELSY); + + //We got pixel units, convert them to logical HIMETRIC along the display + prcHiMetric->right=MAP_PIX_TO_LOGHIM(iXextInPix, iXppli); + prcHiMetric->top =MAP_PIX_TO_LOGHIM(iYextInPix, iYppli); + + prcHiMetric->left =0; + prcHiMetric->bottom =0; + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return; + } + +void SO_MetricSizeInPixelsToHimetric( LPSIZEL pSizeInPix, LPSIZEL pSizeInHiMetric) + { + int iXppli; //Pixels per logical inch along width + int iYppli; //Pixels per logical inch along height + BOOL fSystemDC=FALSE; + + HDC hDC=GetDC(NULL); + fSystemDC=TRUE; + + iXppli=GetDeviceCaps (hDC, LOGPIXELSX); + iYppli=GetDeviceCaps (hDC, LOGPIXELSY); + + //We got pixel units, convert them to logical HIMETRIC along the display + pSizeInHiMetric->cx=(long)MAP_PIX_TO_LOGHIM((int)pSizeInPix->cx, iXppli); + pSizeInHiMetric->cy=(long)MAP_PIX_TO_LOGHIM((int)pSizeInPix->cy, iYppli); + + if (fSystemDC) + ReleaseDC(NULL, hDC); + + return; + } + +/* + * RectConvertMappings + * + * Purpose: + * Converts the contents of a rectangle from device to logical + * coordinates where the hDC defines the logical coordinates. + * + * Parameters: + * pRect LPRECT containing the rectangle to convert. + * hDC HDC describing the logical coordinate system. + * if NULL, uses a screen DC in MM_LOMETRIC. + * fToDevice WIN_BOOL TRUE to convert from uConv to device, + * FALSE to convert device to uConv. + * + * Return Value: + * None + */ + +void RectConvertMappings(LPRECT pRect, HDC hDC, WIN_BOOL fToDevice) + { + POINT rgpt[2]; + WIN_BOOL fSysDC=FALSE; + + if (NULL==pRect) + return; + + rgpt[0].x=pRect->left; + rgpt[0].y=pRect->top; + rgpt[1].x=pRect->right; + rgpt[1].y=pRect->bottom; + + if (NULL==hDC) + { + hDC=GetDC(NULL); + SetMapMode(hDC, MM_HIMETRIC); + //SetMapMode(hDC, MM_LOMETRIC); + fSysDC=TRUE; + } + + if (fToDevice) + LPtoDP(hDC, rgpt, 2); + else + DPtoLP(hDC, rgpt, 2); + + if (fSysDC) + ReleaseDC(NULL, hDC); + + pRect->left=rgpt[0].x; + pRect->top=rgpt[0].y; + pRect->right=rgpt[1].x; + pRect->bottom=rgpt[1].y; + + return; + } + +/* + * CSO_Cont::CSO_Cont + * CSO_Cont::~CSO_Cont + * + * Constructor Parameters: + * dwID DWORD identifier for this page. + * hWnd HWND of the pages window. + * pPG PCPages to the parent structure. + */ + +CSO_Cont::CSO_Cont(DWORD dwID, HWND hWnd, SvOutPlaceObject * pPG) +//CSO_Cont::CSO_Cont(DWORD dwID, HWND hWnd, PCPages pPG) + { + m_hWnd=hWnd; + m_dwID=dwID; + + m_fInitialized=0; + m_pIStorage=NULL; + pTmpStorage=NULL; + m_cOpens=0; + + m_pObj=NULL; + m_pPG =pPG; + m_clsID=CLSID_NULL; + m_fSetExtent=FALSE; + + //CHAPTER17MOD + m_cRef=0; + m_pIOleObject=NULL; + m_pIViewObject2=NULL; + m_grfMisc=0; + + m_pImpIOleClientSite=NULL; + m_pImpIAdviseSink=NULL; + + m_fRepaintEnabled=TRUE; + //End CHAPTER17MOD + return; + } + + +CSO_Cont::~CSO_Cont(void) + { + //CHAPTER17MOD + //Object pointers cleaned up in Close. + + DeleteInterfaceImp(m_pImpIAdviseSink); + DeleteInterfaceImp(m_pImpIOleClientSite); + //End CHAPTER17MOD + + return; + } + + + + +//CHAPTER17MOD +/* + * CSO_Cont::QueryInterface + * CSO_Cont::AddRef + * CSO_Cont::Release + * + * Purpose: + * IUnknown members for CSO_Cont object. + */ + +STDMETHODIMP CSO_Cont::QueryInterface(REFIID riid, PPVOID ppv) + { + *ppv=NULL; + + if (IID_IUnknown==riid) + *ppv=this; + + if (IID_IOleClientSite==riid) + *ppv=m_pImpIOleClientSite; + + if (IID_IAdviseSink==riid) + *ppv=m_pImpIAdviseSink; + + if (NULL!=*ppv) + { + ((LPUNKNOWN)*ppv)->AddRef(); + return NOERROR; + } + + return ResultFromScode(E_NOINTERFACE); + } + + +STDMETHODIMP_(ULONG) CSO_Cont::AddRef(void) + { + return ++m_cRef; + } + +STDMETHODIMP_(ULONG) CSO_Cont::Release(void) + { + if (0!=--m_cRef) + return m_cRef; + + delete this; + return 0; + } + +//End CHAPTER17MOD + + + + + +/* + * CSO_Cont::GetID + * + * Return Value: + * DWORD dwID field in this tenant. + */ + +DWORD CSO_Cont::GetID(void) + { + return m_dwID; + } + + + +/* + * CSO_Cont::GetStorageName + * + * Parameters: + * pszName LPOLESTR to a buffer in which to store the storage + * name for this tenant. + * + * Return Value: + * UINT Number of characters stored. + */ + +//UINT CSO_Cont::GetStorageName(LPOLESTR pszName) +String CSO_Cont::GetStorageName() +{ + // used in SvOutPlaceObject too, don't change name + return String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "Ole-Object" ) ); +} + + + +//CHAPTER17MOD +/* + * CSO_Cont::StorageGet + * + * Purpose: + * Returns the IStorage pointer maintained by this tenant, + * AddRef'd of course. + * + * Parameters: + * ppStg LPSTORAGE * in which to return the pointer. + * + * Return Value: + * None + */ + +/* MM ??? +void CSO_Cont::StorageGet(LPSTORAGE *ppStg) + { + if (NULL==ppStg) + return; + + *ppStg=m_pIStorage; + + if (NULL!=*ppStg) + (*ppStg)->AddRef(); + + return; + } +*/ +//End CHAPTER17MOD + + + + +/* + * CSO_Cont::Create + * + * Purpose: + * Creates a new tenant of the given CLSID, which can be either a + * static bitmap or metafile or any compound document object. + * + * Parameters: + * tType TENANTTYPE to create, either a static metafile, + * bitmap, or some kind of compound document object + * This determines which OleCreate* call we use. + * pvType LPVOID providing the relevant pointer from which + * to create the tenant, depending on iType. + * pFE LPFORMATETC specifying the type of renderings + * to use. + * pptl PPOINTL in which we store offset coordinates. + * pszl LPSIZEL where this object should store its + * lometric extents. + * pIStorage LPSTORAGE of the page we live in. We have to + * create another storage in this for the tenant. + * ppo PPATRONOBJECT containing placement data. + * dwData DWORD with extra data, sensitive to iType. + * + * Return Value: + * UINT A CREATE_* value depending on what we + * actually do. + */ + +UINT CSO_Cont::Create(TENANTTYPE tType, LPVOID pvType + , LPFORMATETC pFE, PPOINTL pptl, LPSIZEL pszl + , SotStorage * pIStorage, PPATRONOBJECT ppo, DWORD dwData) +// , LPSTORAGE pIStorage, PPATRONOBJECT ppo, DWORD dwData) + { + HRESULT hr; + LPUNKNOWN pObj = NULL; + UINT uRet=CREATE_GRAPHICONLY; + //CHAPTER17MOD + //Some things moves to ObjectInitialize + //End CHAPTER17MOD + + if (NULL==pvType || NULL==pIStorage) + return CREATE_FAILED; + + //Fail if this is called for an already living tenant. + if (m_fInitialized) + return CREATE_FAILED; + + m_fInitialized=TRUE; + + //Create a new storage for this tenant. + if (!Open(pIStorage)) + return CREATE_FAILED; + + /* + * Get the placement info if it's here. We either have a non- + * NULL PPATRONOBJECT in ppo or we have to use default + * placement and retrieve the size from the object itself. + */ + pszl->cx=0; + pszl->cy=0; + + if (NULL!=ppo) + { + *pFE=ppo->fe; + *pptl=ppo->ptl; + *pszl=ppo->szl; //Could be 0,0 , so we ask object + + uRet=CREATE_PLACEDOBJECT; + } + + hr=ResultFromScode(E_FAIL); + + //Now create an object based specifically for the type. + switch (tType) + { + case TENANTTYPE_NULL: + break; + + case TENANTTYPE_STATIC: + /* + * We could use OleCreateStaticFromData here which does + * pretty much what we're doing below. However, it does + * not allow us to control whether we paste a bitmap or + * a metafile--it uses metafile first, bitmap second. + * For this reason we'll use code developed in Chapter + * 11's FreeLoader to affect the paste. + */ + hr=CreateStatic((LPDATAOBJECT)pvType, pFE, &pObj); + break; + + //CHAPTER17MOD + case TENANTTYPE_EMBEDDEDOBJECT: + hr=OleCreate(*((LPCLSID)pvType), IID_IUnknown + , OLERENDER_DRAW, NULL, NULL, m_pIStorage + , (PPVOID)&pObj); + break; + + case TENANTTYPE_EMBEDDEDFILE: + hr=StarObject_OleCreateFromFile(CLSID_NULL, (LPTSTR)pvType + , IID_IUnknown, OLERENDER_DRAW, NULL, NULL + , m_pIStorage, (PPVOID)&pObj); + break; + + case TENANTTYPE_EMBEDDEDOBJECTFROMDATA: + hr=OleCreateFromData((LPDATAOBJECT)pvType, IID_IUnknown + , OLERENDER_DRAW, NULL, NULL, m_pIStorage + , (PPVOID)&pObj); + break; + //End CHAPTER17MOD + + default: + break; + } + + //If creation didn't work, get rid of the element Open created. + if (FAILED(hr)) + { + Destroy(pIStorage); + return CREATE_FAILED; + } + + //CHAPTER17MOD + //We don't get the size if PatronObject data was seen already. + if (!ObjectInitialize(pObj, pFE->dwAspect, dwData)) + //if (!ObjectInitialize(pObj, pFE, dwData)) + { + Destroy(pIStorage); + return CREATE_FAILED; + } + + if (0==pszl->cx && 0==pszl->cy) + { + GetExtent( pszl ); + } + //End CHAPTER17MOD + + return uRet; + } + + + +/* + * CSO_Cont::Save + * + * Purpose: + * + * Parameters: + * pIStorage LPSTORAGE of the page we live in. + * + * Return Value: + * WIN_BOOL TRUE if successful, FALSE otherwise. + */ + +WIN_BOOL CSO_Cont::Save(SotStorage *pIStorage) + { + LPPERSISTSTORAGE pIPS; + + if (NULL!=m_pIStorage) + { + /* + * We need to OleSave again because we might have changed + * the size or position of this tenant. We also need to + * save the rectangle on the page, since that's not known + * to OLE. + */ + m_pObj->QueryInterface(IID_IPersistStorage, (PPVOID)&pIPS); + + //This fails for static objects...so we improvise if so + if (FAILED(OleSave(pIPS, m_pIStorage, TRUE))) + { + //This is essentially what OleSave does. + WriteClassStg(m_pIStorage, m_clsID); + pIPS->Save(m_pIStorage, TRUE); + } + + pIPS->SaveCompleted(NULL); + pIPS->Release(); + m_pIStorage->Commit(STGC_DEFAULT); + + // copy to SotStream + // Create the stream + String szTemp = GetStorageName(); + SotStorageStreamRef xStm = pIStorage->OpenSotStream( szTemp, STREAM_STD_READWRITE ); + if( xStm->GetError() ) + return FALSE; + //We know we only hold one ref from Create or Load + HGLOBAL hGlobal = NULL; + GetHGlobalFromILockBytes( + pTmpStorage, //Pointer to the byte array object + &hGlobal );//Pointer to the current memory handle for the specified byte array + if( !hGlobal ) + return FALSE; + void * pMem = GlobalLock( hGlobal ); + if( !pMem ) + return FALSE; + xStm->SetSize( 0 ); + ULONG nMaxLen = GlobalSize( hGlobal ); + xStm->Write( pMem, nMaxLen ); +//SvFileStream aFS( "d:\\temp\\test.ttt", STREAM_STD_READWRITE ); +//aFS.Write( pMem, nMaxLen ); + GlobalUnlock( hGlobal ); + + return TRUE; + } + + return FALSE; + } + + + +/* + * CSO_Cont::Load + * + * Purpose: + * Recreates the object living in this tenant in place of calling + * FCreate. This is used in loading as opposed to new creation. + * + * Parameters: + * pIStorage LPSTORAGE of the page we live in. + * pti PTENTANTINFO containing persistent information. + * The ID value in this structure is ignored. + * + * Return Value: + * WIN_BOOL TRUE if successful, FALSE otherwise. + */ + +//WIN_BOOL CSO_Cont::Load(LPSTORAGE pIStorage, PTENANTINFO pti) +WIN_BOOL CSO_Cont::Load(SotStorage *pIStorage, DWORD dwAspect, WIN_BOOL fSetExtent, RECTL & rcl ) + { + HRESULT hr; + LPUNKNOWN pObj; + //CHAPTER17MOD + DWORD dwState=TENANTSTATE_DEFAULT; + //End CHAPTER17MOD + + /* + if (NULL==pIStorage || NULL==pti) + return FALSE; + */ + + //CHAPTER17MOD + /* + * If we already initialized once, clean up, releasing + * everything before we attempt to reload. This happens + * when using the Convert Dialog. + */ + if (m_fInitialized) + { + //Preserve all states except open + dwState=(m_dwState & ~TENANTSTATE_OPEN); + m_cRef++; //Prevent accidental closure + + //This should release all holds on our IStorage as well. + if (NULL!=m_pIViewObject2) + { + m_pIViewObject2->SetAdvise(dwAspect, 0, NULL); +// m_pIViewObject2->SetAdvise(m_fe.dwAspect, 0, NULL); + ReleaseInterface(m_pIViewObject2); + } + + ReleaseInterface(m_pIOleObject); + ReleaseInterface(m_pObj); + + m_pIStorage=NULL; //We'll have already released this. + pTmpStorage=NULL; //We'll have already released this. + m_cRef--; //Match safety increment above. + } + //End CHAPTER14MOD + + m_fInitialized=TRUE; + + //Open the storage for this tenant. + if (!Open(pIStorage)) + return FALSE; + + hr=OleLoad(m_pIStorage, IID_IUnknown, NULL, (PPVOID)&pObj); + + if (FAILED(hr)) + { + Destroy(pIStorage); + return FALSE; + } + + //CHAPTER17MOD + m_fSetExtent=fSetExtent; + //m_fSetExtent=pti->fSetExtent; + ObjectInitialize(pObj, dwAspect, NULL); + //ObjectInitialize(pObj, &pti->fe, NULL); + + //Restore the original state before reloading. + m_dwState=dwState; + //End CHAPTER17MOD + + RectSet(&rcl, FALSE, FALSE); + //RectSet(&pti->rcl, FALSE, FALSE); + return TRUE; + } + + + + +/* + * CSO_Cont::GetInfo + * + * Purpose: + * Retrieved a TENANTINFO structure for this tenant. + * + * Parameters: + * pti PTENANTINFO structure to fill + * + * Return Value: + * None + */ + +//void CSO_Cont::GetInfo(PTENANTINFO pti) +void CSO_Cont::GetInfo(DWORD& rAspect, WIN_BOOL & rSetExtend ) +{ + rAspect = dwAspect; + rSetExtend = m_fSetExtent; + /* + if (NULL!=pti) + { + pti->dwID=m_dwID; + pti->rcl=m_rcl; + pti->fe=m_fe; + pti->fSetExtent=m_fSetExtent; + } + + return; + */ +} + + + + +//CHAPTER17MOD +/* + * CSO_Cont::ObjectInitialize + * (Protected) + * + * Purpose: + * Performs operations necessary after creating an object or + * reloading one from storage. + * + * Parameters: + * pObj LPUNKNOWN of the object in this tenant. + * pFE LPFORMATETC describing the graphic here. + * dwData DWORD extra data. If pFE->dwAspect== + * DVASPECT_ICON then this is the iconic metafile. + * + * Return Value: + * WIN_BOOL TRUE if the function succeeded, FALSE otherwise. + */ + +//WIN_BOOL CSO_Cont::ObjectInitialize(LPUNKNOWN pObj, LPFORMATETC pFE, DWORD dwData) +WIN_BOOL CSO_Cont::ObjectInitialize(LPUNKNOWN pObj, DWORD dwAspect_, DWORD dwData) + { + HRESULT hr; + LPPERSIST pIPersist=NULL; + DWORD dw; + //PCDocument pDoc; + TCHAR szFile[CCHPATHMAX]; + + //if (NULL==pObj || NULL==pFE) + // return FALSE; + + m_pObj=pObj; + dwAspect = dwAspect_; + //m_fe=*pFE; + //m_fe.ptd=NULL; + m_dwState=TENANTSTATE_DEFAULT; + + /* + * Determine the type: Static or Embedded. If Static, + * this will have CLSID_Picture_Metafile or CLSID_Picture_Dib. + * Otherwise it's embedded. Later we'll add a case for links. + */ + m_tType=TENANTTYPE_EMBEDDEDOBJECT; + + if (SUCCEEDED(pObj->QueryInterface(IID_IPersist + , (PPVOID)&pIPersist))) + { + CLSID clsid=CLSID_NULL; + + hr=pIPersist->GetClassID(&clsid); + + //If we don't have a CLSID, default to static + if (FAILED(hr) || CLSID_Picture_Metafile==clsid + || CLSID_Picture_Dib==clsid) + m_tType=TENANTTYPE_STATIC; + + pIPersist->Release(); + } + + + m_pIViewObject2=NULL; + hr=pObj->QueryInterface(IID_IViewObject2 + , (PPVOID)&m_pIViewObject2); + + if (FAILED(hr)) + return FALSE; + + m_pIViewObject2->SetAdvise(dwAspect, 0, m_pImpIAdviseSink); + //m_pIViewObject2->SetAdvise(m_fe.dwAspect, 0, m_pImpIAdviseSink); + + IOleCache* pIOleCache = NULL; + if ( SUCCEEDED(m_pIViewObject2->QueryInterface(IID_IOleCache, (PPVOID)&pIOleCache)) && pIOleCache ) + { + IEnumSTATDATA* pEnumSD = NULL; + HRESULT hr = pIOleCache->EnumCache( &pEnumSD ); + + sal_Bool bRegister = sal_True; + if ( SUCCEEDED( hr ) && pEnumSD ) + { + pEnumSD->Reset(); + STATDATA aSD; + DWORD nNum; + while( SUCCEEDED( pEnumSD->Next( 1, &aSD, &nNum ) ) && nNum == 1 ) + { + if ( aSD.formatetc.cfFormat == 0 ) + { + bRegister = sal_False; + break; + } + } + } + + if ( bRegister ) + { + DWORD nConn; + FORMATETC aFormat = { 0, 0, ASPECT_CONTENT, -1, TYMED_MFPICT }; + hr = pIOleCache->Cache( &aFormat, /*ADVFCACHE_FORCEBUILTIN*/ /*ADVF_PRIMEFIRST*/ ADVFCACHE_ONSAVE, &nConn ); +/* + IDataObject* pIDataObject = NULL; + if ( SUCCEEDED(pObj->QueryInterface(IID_IDataObject, (PPVOID)&pIDataObject)) && pIDataObject ) + { + pIOleCache->InitCache( pIDataObject ); + pIDataObject->Release(); + pIDataObject = NULL; + } +*/ + } + + pIOleCache->Release(); + pIOleCache = NULL; + } + + + //We need an IOleObject most of the time, so get one here. + m_pIOleObject=NULL; + hr=pObj->QueryInterface(IID_IOleObject + , (PPVOID)&m_pIOleObject); + + /* + * Follow up object creation with advises and so forth. If + * we cannot get IOleObject here, then we know we can't do + * any IOleObject actions from here on--object is static. + */ + if (FAILED(hr)) + return TRUE; + + /* + * Get the MiscStatus bits and check for OLEMISC_ONLYICONIC. + * If set, force dwAspect in m_fe to DVASPECT_ICON so we + * remember to draw it properly and do extents right. + */ + m_pIOleObject->GetMiscStatus(dwAspect, &m_grfMisc); + //m_pIOleObject->GetMiscStatus(m_fe.dwAspect, &m_grfMisc); + + if (OLEMISC_ONLYICONIC & m_grfMisc) + dwAspect=DVASPECT_ICON; + //m_fe.dwAspect=DVASPECT_ICON; + + /* + * We could pass m_pImpIOleClientSite in an OleCreate* call, but + * since this function could be called after OleLoad, we still + * need to do this here, so it's always done here... + */ + m_pIOleObject->SetClientSite(m_pImpIOleClientSite); + m_pIOleObject->Advise(m_pImpIAdviseSink, &dw); + + OleSetContainedObject(m_pIOleObject, TRUE); + + /* + * For IOleObject::SetHostNames we need the application name + * and the document name (which is passed in the object + * parameter). The design of Patron doesn't give us nice + * structured access to the name of the document we're in, so + * I grab the parent of the Pages window (the document) and + * send it DOCM_PDOCUMENT which returns us the pointer. + * Roundabout, but it works. + */ + + /* MM ??? + pDoc=(PCDocument)SendMessage(GetParent(m_hWnd), DOCM_PDOCUMENT + , 0, 0L); + + if (NULL!=pDoc) + pDoc->FilenameGet(szFile, CCHPATHMAX); + else + */ + szFile[0]=0; + + NotifyOfRename(szFile, NULL); + + + /* + * If we're creating an iconic aspect object and we have + * an object from the Insert Object dialog, then we need to + * store that iconic presentation in the cache, handled + * with the utility function StarObject_SwitchDisplayAspect. In + * this case dwData is a handle to the metafile containing + * the icon. If dwData is NULL then we depend on the + * server to provide the aspect, in which case we need + * a view advise. + */ + + //if (DVASPECT_ICON & m_fe.dwAspect) + if (DVASPECT_ICON & dwAspect) + { + DWORD dw=DVASPECT_CONTENT; + IAdviseSink *pSink; + + pSink=(NULL==dwData) ? NULL : m_pImpIAdviseSink; + + StarObject_SwitchDisplayAspect(m_pIOleObject, &dw + , DVASPECT_ICON, (HGLOBAL)(UINT)dwData, FALSE + , (NULL!=dwData), pSink, NULL); + } + + return TRUE; + } +//End CHAPTER17MOD + + + + +/* + * CSO_Cont::Open + * + * Purpose: + * Retrieves the IStorage associated with this tenant. The + * IStorage is owned by the tenant and thus the tenant always + * holds a reference count. + * + * If the storage is already open for this tenant, then this + * function will AddRef it; therefore the caller must always + * match an Open with a Close. + * + * Parameters: + * pIStorage LPSTORAGE above this tenant (which has its + * own storage). + * + * Return Value: + * WIN_BOOL TRUE if opening succeeds, FALSE otherwise. + */ + +//WIN_BOOL CSO_Cont::Open(LPSTORAGE pIStorage) +WIN_BOOL CSO_Cont::Open(SotStorage * pIStorage) + { + /* + HRESULT hr=NOERROR; + DWORD dwMode=STGM_TRANSACTED | STGM_READWRITE + | STGM_SHARE_EXCLUSIVE; + OLECHAR szTemp[32]; + */ + + if (NULL==m_pIStorage) + { + if (NULL==pIStorage) + return FALSE; + + /* + * Attempt to open the storage under this ID. If there is + * none, then create it. In either case we end up with an + * IStorage that we either save in pPage or release. + */ + +// StgCreateDocfile( "d:\\temp\\test.ttt", STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, &m_pIStorage ); + + SotStorageStreamRef xStm; + String szTemp = GetStorageName(); + if( pIStorage->IsContained( szTemp ) ) + { + xStm = pIStorage->OpenSotStream( szTemp, STREAM_STD_READ ); + if( xStm->GetError() ) + return FALSE; + xStm->Seek( STREAM_SEEK_TO_END ); + UINT32 nLen = xStm->Tell(); + xStm->Seek( 0 ); + HGLOBAL hMem = GlobalAlloc( GMEM_MOVEABLE | GMEM_SHARE, nLen ); + void * pMem = GlobalLock( hMem ); + if( pMem ) + xStm->Read( pMem, nLen ); + else + return FALSE; + GlobalUnlock( hMem ); + xStm = NULL; + + CreateILockBytesOnHGlobal( + hMem, //Memory handle for the byte array object + TRUE, //Whether to free memory when the object is released + &pTmpStorage //Indirect pointer to the new byte array object + ); + if( !pTmpStorage ) + return FALSE; + + HRESULT hr = StgOpenStorageOnILockBytes( + pTmpStorage, //Pointer to the byte array object + NULL, + STGM_READWRITE | STGM_SHARE_EXCLUSIVE, //Access mode + NULL, + 0, //Reserved; must be zero + &m_pIStorage //Indirect pointer to the new storage object + ); + if( FAILED( hr ) ) + return FALSE; + } + else + { + CreateILockBytesOnHGlobal( + NULL, //Memory handle for the byte array object + TRUE, //Whether to free memory when the object is released + &pTmpStorage //Indirect pointer to the new byte array object + ); + if( !pTmpStorage ) + return FALSE; + + StgCreateDocfileOnILockBytes( + pTmpStorage, //Pointer to the byte array object + STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, //Access mode + 0, //Reserved; must be zero + &m_pIStorage //Indirect pointer to the new storage object + ); + } + + /* MM ??? StgOpenStorage + GetStorageName(szTemp); + hr=pIStorage->OpenStorage(szTemp, NULL, dwMode, NULL, 0 + , &m_pIStorage); + + if (FAILED(hr)) + { + hr=pIStorage->CreateStorage(szTemp, dwMode, 0, 0 + , &m_pIStorage); + } + if (FAILED(hr)) + return FALSE; + */ + } + else + { + m_pIStorage->AddRef(); + pTmpStorage->AddRef(); + } + + + m_cOpens++; + + //CHAPTER17MOD + //Create these if we don't have them already. + if (NULL==m_pImpIOleClientSite && NULL==m_pImpIAdviseSink) + { + m_pImpIOleClientSite=new CImpIOleClientSite(this, this); + m_pImpIAdviseSink=new CImpIAdviseSink(this, this); + + if (NULL==m_pImpIOleClientSite || NULL==m_pImpIAdviseSink) + return FALSE; + } + //End CHAPTER17MOD + + return TRUE; + } + + + + +/* + * CSO_Cont::Close + * + * Purpose: + * Possibly commits the storage, then releases it reversing the + * reference count from Open. If the reference on the storage + * goes to zero, the storage is forgotten. However, the object we + * contain is still held and as long as it's active the storage + * remains alive. + * + * Parameters: + * fCommit WIN_BOOL indicating if we're to commit. + * + * Return Value: + * None + */ + +//void CSO_Cont::Close(WIN_BOOL fCommit) +void CSO_Cont::Close(WIN_BOOL fCommit) + { + if (fCommit) + Update(); + + if (NULL!=m_pIStorage) + { + m_pIStorage->Release(); + pTmpStorage->Release(); + + /* + * We can't use a zero reference count to know when to NULL + * this since other things might have AddRef'd the storage. + */ + //CHAPTER17MOD + if (0==--m_cOpens) + { + m_pIStorage=NULL; + pTmpStorage=NULL; + + //Close the object saving if necessary + if (NULL!=m_pIOleObject) + { + m_pIOleObject->Close( fCommit ? OLECLOSE_SAVEIFDIRTY : OLECLOSE_NOSAVE ); + ReleaseInterface(m_pIOleObject); + } + + //Release all other held pointers + if (NULL!=m_pIViewObject2) + { + m_pIViewObject2->SetAdvise(dwAspect, 0, NULL); + //m_pIViewObject2->SetAdvise(m_fe.dwAspect, 0, NULL); + ReleaseInterface(m_pIViewObject2); + } + + ReleaseInterface(m_pObj); + } + //End CHAPTER17MOD + } + + return; + } + + + + +/* + * CSO_Cont::Update + * + * Purpose: + * Forces a common on the page if it's open. + * + * Parameters: + * None + * + * Return Value: + * WIN_BOOL TRUE if the object is open, FALSE otherwise. + */ + +//WIN_BOOL CSO_Cont::Update(void) +WIN_BOOL CSO_Cont::Update() + { + Save( m_pPG->GetWorkingStorage()); + m_pPG->ClearCache(); + m_pPG->ViewChanged( (UINT16)dwAspect ); + m_pPG->SendViewChanged(); + + return FALSE; + } + + + + + +/* + * CSO_Cont::Destroy + * + * Purpose: + * Removes this page from the given storage. The caller should + * eventually delete this CSO_Cont object to free the object herein. + * Nothing is committed when being destroyed. + * + * Parameters: + * pIStorage LPSTORAGE contianing this page on which to call + * DestroyElement + * + * Return Value: + * None + */ + +//void CSO_Cont::Destroy(LPSTORAGE pIStorage) +void CSO_Cont::Destroy(SotStorage * pIStorage) + { + if (NULL!=pIStorage) + { + //CHAPTER17MOD + if (NULL!=m_pIOleObject) + m_pIOleObject->Close(OLECLOSE_NOSAVE); + //End CHAPTER17MOD + + if (NULL!=m_pIStorage) + { + //Remove all reference/open counts on this storage. + while (0!=m_cOpens) + { + m_pIStorage->Release(); + pTmpStorage->Release(); + m_cOpens--; + } + } + + String szTemp = GetStorageName(); + pIStorage->Remove(szTemp); + //GetStorageName(szTemp); + //pIStorage->DestroyElement(szTemp); + + m_pIStorage=NULL; + pTmpStorage = NULL; + } + + return; + } + + + + +/* + * CSO_Cont::Select + * + * Purpose: + * Selects or deselects the tenant. + * + * Parameters: + * fSelect WIN_BOOL indicating the new state of the tenant. + * + * Return Value: + * None + */ + +void CSO_Cont::Select(WIN_BOOL fSelect) + { + WIN_BOOL fWasSelected; + DWORD dwState; + RECT rc; + + fWasSelected=(WIN_BOOL)(TENANTSTATE_SELECTED & m_dwState); + + //Nothing to do when there's no change. + if (fWasSelected==fSelect) + return; + + dwState=m_dwState & ~TENANTSTATE_SELECTED; + m_dwState=dwState | ((fSelect) ? TENANTSTATE_SELECTED : 0); + + /* + * Draw sizing handles to show the selection state. We convert + * things to MM_TEXT since that's what this function expects. + */ + + RECTFROMRECTL(rc, m_rcl); + RectConvertMappings(&rc, NULL, TRUE); + + /* MM ??? + OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos); + + hDC=GetDC(m_hWnd); + + UIDrawHandles(&rc, hDC, UI_HANDLES_INSIDE + | UI_HANDLES_NOBORDER | UI_HANDLES_USEINVERSE + , CXYHANDLE, !fWasSelected); + + ReleaseDC(m_hWnd, hDC); + */ + + if (fSelect) + m_pPG->SetModified(); + //m_pPG->m_fDirty=TRUE; + + return; + } + + + + +//CHAPTER17MOD +/* + * CSO_Cont::ShowAsOpen + * + * Purpose: + * Draws or removes the hatch pattern over an object. + * + * Parameters: + * fOpen WIN_BOOL indicating the open state of this tenant. + * + * Return Value: + * None + */ + +void CSO_Cont::ShowAsOpen(WIN_BOOL fOpen) + { + WIN_BOOL fWasOpen; + DWORD dwState; + RECT rc; + + fWasOpen=(WIN_BOOL)(TENANTSTATE_OPEN & m_dwState); + + dwState=m_dwState & ~TENANTSTATE_OPEN; + m_dwState=dwState | ((fOpen) ? TENANTSTATE_OPEN : 0); + + //If this was not open, then just hatch, otherwise repaint. + if (!fWasOpen && fOpen) + { + RECTFROMRECTL(rc, m_rcl); + RectConvertMappings(&rc, NULL, TRUE); + /* MM ??? + OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos); + + hDC=GetDC(m_hWnd); + UIDrawShading(&rc, hDC, UI_SHADE_FULLRECT, 0); + ReleaseDC(m_hWnd, hDC); + */ + } + + if (fWasOpen && !fOpen) + { + m_pPG->GetProtocol().Reset2Open(); + + Repaint(); + } + else if (!fWasOpen && fOpen) + { + m_pPG->GetProtocol().EmbedProtocol(); + } + + return; + } + + + + + +/* + * CSO_Cont::ShowYourself + * + * Purpose: + * Function that really just implements IOleClientSite::ShowObject. + * Here we first check if the tenant is fully visible, and if so, + * then nothing needs to happen. Otherwise, if the upper left + * corner of the tenant is in the upper left visible quadrant of + * the window, we'll also consider ourselves done. Otherwise + * we'll put the upper left corner of the object at the upper left + * corner of the window. + * + * Parameters: + * None + * + * Return Value: + * None + */ + +void CSO_Cont::ShowYourself(void) + { + RECTL rcl; + RECT rc; + + //Scrolling deals in device units; get our rectangle in those. + RectGet(&rcl, TRUE); + + //Get the window rectangle offset for the current scroll pos. + GetClientRect(m_hWnd, &rc); + /* MM ??? + OffsetRect(&rc, m_pPG->m_xPos, m_pPG->m_yPos); + + //Check if the object is already visible. (macro in bookguid.h) + SETPOINT(pt1, (int)rcl.left, (int)rcl.top); + SETPOINT(pt2, (int)rcl.right, (int)rcl.bottom); + + if (PtInRect(&rc, pt1) && PtInRect(&rc, pt2)) + return; + + //Check if the upper left is within the upper left quadrant + if (((int)rcl.left > rc.left + && (int)rcl.left < ((rc.right+rc.left)/2)) + && ((int)rcl.top > rc.top + && (int)rcl.top < ((rc.bottom+rc.top)/2))) + return; + + //These are macros in INC\BOOK1632.H + SendScrollPosition(m_hWnd, WM_HSCROLL, rcl.left-8); + SendScrollPosition(m_hWnd, WM_VSCROLL, rcl.top-8); + */ + return; + } + + + +/* + * CSO_Cont::AddVerbMenu + * + * Purpose: + * Creates the variable verb menu item for the object in this + * tenant. + * + * Parmeters: + * hMenu HMENU on which to add items. + * iPos UINT position on that menu to add items. + * + * Return Value: + * None + */ + +void CSO_Cont::AddVerbMenu(HMENU, UINT) + { + /* MM ??? + HMENU hMenuTemp; + LPOLEOBJECT pObj=m_pIOleObject; + + //If we're static, say we have no object. + if (TENANTTYPE_STATIC==m_tType) + pObj=NULL; + + OleUIAddVerbMenu(pObj, NULL, hMenu, iPos, IDM_VERBMIN + , IDM_VERBMAX, TRUE, IDM_EDITCONVERT, &hMenuTemp); + + return; + */ + } + + + + +/* + * CSO_Cont::TypeGet + * + * Purpose: + * Returns the type of this tenant + * + * Parameters: + * None + * + * Return Value: + * TENANTTYPE Type of the tenant. + */ + +TENANTTYPE CSO_Cont::TypeGet(void) + { + return m_tType; + } + + + + + + +/* + * CSO_Cont::CopyEmbeddedObject + * + * Purpose: + * Copies an embedded object to the given data object (via SetData, + * assuming this is a data transfer object for clipboard/drag-drop) + * if that's what we're holding. + * + * Parameters: + * pIDataObject LPDATAOBJECT in which to store the copy. + * pFE LPFORMATETC into which to copy CFSTR_EMBEDDEDOBJECT + * if we put that in the data object. + * pptl PPOINTL to the pick point (NULL outside of + * drag-drop); + * + * Return Value: + * None + */ + +void CSO_Cont::CopyEmbeddedObject(LPDATAOBJECT pIDataObject + , LPFORMATETC pFE, PPOINTL pptl) + { + LPPERSISTSTORAGE pIPS; + STGMEDIUM stm; + FORMATETC fe; + HRESULT hr; + UINT cf; + POINTL ptl; + SIZEL szl; + + //Can only copy embeddings. + if (TENANTTYPE_EMBEDDEDOBJECT!=m_tType || NULL==m_pIOleObject) + return; + + if (NULL==pptl) + { + SETPOINTL(ptl, 0, 0); + pptl=&ptl; + } + + /* + * Create CFSTR_EMBEDDEDOBJECT. This is simply an IStorage with + * a copy of the embedded object in it. The not-so-simple part + * is getting an IStorage to stuff it in. For this operation + * we'll use a temporary compound file. + */ + + stm.pUnkForRelease=NULL; + stm.tymed=TYMED_ISTORAGE; + hr=StgCreateDocfile(NULL, STGM_TRANSACTED | STGM_READWRITE + | STGM_CREATE| STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE + , 0, &stm.pstg); + + if (FAILED(hr)) + return; + + m_pObj->QueryInterface(IID_IPersistStorage, (PPVOID)&pIPS); + + if (NOERROR==pIPS->IsDirty()) + { + OleSave(pIPS, stm.pstg, FALSE); + pIPS->SaveCompleted(NULL); + } + else + m_pIStorage->CopyTo(0, NULL, NULL, stm.pstg); + + pIPS->Release(); + + //stm.pstg now has a copy, so stuff it away. + cf=RegisterClipboardFormat(CFSTR_EMBEDDEDOBJECT); + SETDefFormatEtc(fe, sal::static_int_cast< CLIPFORMAT >(cf), TYMED_ISTORAGE); + + if (SUCCEEDED(pIDataObject->SetData(&fe, &stm, TRUE))) + *pFE=fe; + else + ReleaseStgMedium(&stm); + + stm.tymed=TYMED_HGLOBAL; + + /* + * You want to make sure that if this object is iconic, that you + * create the object descriptor with DVASPECT_ICON instead of + * the more typical DVASPECT_CONTENT. Also remember that + * the pick point is in HIMETRIC. + */ + SO_MetricSizeInPixelsToHimetric( (LPSIZEL)pptl, (LPSIZEL)&ptl); + + //SETSIZEL(szl, (10*(m_rcl.right-m_rcl.left)) + // , (10 * (m_rcl.bottom-m_rcl.top))); + SETSIZEL(szl, m_rcl.right-m_rcl.left, m_rcl.bottom-m_rcl.top ); + + stm.hGlobal=StarObject_ObjectDescriptorFromOleObject(m_pIOleObject, dwAspect, ptl, &szl); + //stm.hGlobal=StarObject_ObjectDescriptorFromOleObject(m_pIOleObject, m_fe.dwAspect, ptl, &szl); + + cf=RegisterClipboardFormat(CFSTR_OBJECTDESCRIPTOR); + SETDefFormatEtc(fe, sal::static_int_cast< CLIPFORMAT >(cf), TYMED_HGLOBAL); + + if (FAILED(pIDataObject->SetData(&fe, &stm, TRUE))) + ReleaseStgMedium(&stm); + + return; + } + + + + + +/* + * CSO_Cont::NotifyOfRename + * + * Purpose: + * Instructs the tenant that the document was saved under a + * different name. In order to keep the right compound document + * user interface, this tenant needs to tell its object through + * IOleObject::SetHostNames. + * + * Parameters: + * pszFile LPTSTR of filename. + * pvReserved LPVOID reserved for future use. + * + * Return Value: + * None + */ + +void CSO_Cont::NotifyOfRename(LPTSTR pszFile, LPVOID) + { + TCHAR szObj[40]; + TCHAR szApp[40]; + + if (NULL==m_pIOleObject) + return; + + if (TEXT('\0')==*pszFile) + { + // MM ??? + lstrcpyn( szObj, "untitled", SAL_N_ELEMENTS(szObj) ); + //LoadString(m_pPG->m_hInst, IDS_UNTITLED, szObj, sizeof(szObj)); + } + else + { + // MM ??? + lstrcpyn( szObj, "untitled", SAL_N_ELEMENTS(szObj) ); + //GetFileTitle(pszFile, szObj, sizeof(szObj)); + + #ifndef WIN32 + //Force filenames to uppercase in DOS versions. + AnsiUpper(szObj); + #endif + } + + // MM ??? + lstrcpyn( szApp, "app name", SAL_N_ELEMENTS(szApp) ); + //LoadString(m_pPG->m_hInst, IDS_CAPTION, szApp, sizeof(szApp)); + #ifdef WIN32ANSI + OLECHAR szObjW[40], szAppW[40]; + + MultiByteToWideChar(CP_ACP, 0, szObj, -1, szObjW, 40); + MultiByteToWideChar(CP_ACP, 0, szApp, -1, szAppW, 40); + m_pIOleObject->SetHostNames(szAppW, szObjW); + #else + m_pIOleObject->SetHostNames(szApp, szObj); + #endif + return; + } + +//End CHAPTER17MOD + + + + + +/* + * CSO_Cont::Activate + * + * Purpose: + * Activates a verb on the object living in the tenant. Does + * nothing for static objects. + * + * Parameters: + * iVerb LONG of the verb to execute. + * + * Return Value: + * WIN_BOOL TRUE if the object changed due to this verb + * execution. + */ + +WIN_BOOL CSO_Cont::Activate(LONG iVerb, HWND hParent ) + { + //CHAPTER17MOD + RECT rc, rcH; + //CHourglass *pHour; + SIZEL szl; + + //Can't activate statics. + if (TENANTTYPE_STATIC==m_tType || NULL==m_pIOleObject) + { + MessageBeep(0); + return FALSE; + } + + RECTFROMRECTL(rc, m_rcl); + RectConvertMappings(&rc, NULL, TRUE); + SO_MetricRectInPixelsToHimetric( &rc, &rcH); + + //pHour=new CHourglass; + + //Get the server running first, then do a SetExtent, then show it + OleRun(m_pIOleObject); + + if (m_fSetExtent) + { + SETSIZEL(szl, rcH.right-rcH.left, rcH.top-rcH.bottom); + m_pIOleObject->SetExtent(dwAspect, &szl); + //m_pIOleObject->SetExtent(m_fe.dwAspect, &szl); + m_fSetExtent=FALSE; + } + + if( !hParent ) + hParent = m_hWnd; + HRESULT hr = m_pIOleObject->DoVerb(iVerb, NULL, m_pImpIOleClientSite, 0 + , hParent, &rcH); + + //delete pHour; + + //If object changes, IAdviseSink::OnViewChange will see it. + return SUCCEEDED( hr ); + //End CHAPTER17MOD + } + + +BOOL CSO_Cont::GetMetaFile( long& nMapMode, Size& rSize, HMETAFILE& hMet ) +{ + if ( !m_pObj ) + return FALSE; + + HRESULT hr; + LPDATAOBJECT pIDataObject; + FORMATETC fe; + STGMEDIUM stm; + hr=m_pObj->QueryInterface(IID_IDataObject, (PPVOID)&pIDataObject); + if ( SUCCEEDED(hr) ) + { + if ( !OleIsRunning( m_pIOleObject ) ) + OleRun( m_pObj ); + + SETFormatEtc(fe, CF_METAFILEPICT, DVASPECT_CONTENT, NULL, TYMED_MFPICT, -1); + hr=pIDataObject->GetData(&fe, &stm); + pIDataObject->Release(); + METAFILEPICT* pMem = (METAFILEPICT*) GlobalLock( stm.hGlobal ); + if( !pMem ) + return FALSE; + nMapMode = pMem->mm; + rSize.Width() = pMem->xExt; + rSize.Height() = pMem->yExt; + hMet = pMem->hMF; + GlobalUnlock( stm.hGlobal ); + } + + return TRUE; +} + +/* + * CSO_Cont::Draw + * + * Purpose: + * Draws the tenant in its rectangle on the given hDC. We assume + * the DC is already set up for the mapping mode in which our + * rectangle is expressed, since the Page we're in tells us both + * the rect and the hDC. + * + * Parameters: + * hDC HDC in which to draw. Could be a metafile, + * memory DC, screen, or printer. + * ptd DVTARGETDEVICE * describing the device. + * hIC HDC holding an information context (printing). + * xOff, yOff int offsets for the page in lometric + * fNoColor WIN_BOOL indicating if we should do B & W + * fPrinter WIN_BOOL indicating if we should render for a + * printer. + * + * Return Value: + * None + */ + +void CSO_Cont::Draw(HDC hDC, DVTARGETDEVICE *ptd, HDC hIC + , int xOff, int yOff, WIN_BOOL fNoColor, WIN_BOOL fPrinter) + { + HRESULT hr; + RECT rc = { 0, 0, xOff, -yOff }; + RECTL rcl = { 0, 0, xOff, -yOff }; + UINT uMM; + + //CHAPTER17MOD + //We hold IViewObject2 all the time now, so no QueryInterface + //End CHAPTER17MOD + + //RECTFROMRECTL(rc, m_rcl); + //OffsetRect(&rc, -xOff, -yOff); + //RECTLFROMRECT(rcl, rc); + + //CHAPTER17MOD + //Repaint erases the rectangle to insure full object cleanup + + if (!fNoColor && !fPrinter) + { + COLORREF cr; + cr=SetBkColor(hDC, GetSysColor(COLOR_WINDOW)); + ExtTextOut(hDC, rc.left, rc.top, ETO_OPAQUE, &rc, NULL + , 0, NULL); + SetBkColor(hDC, cr); + } + + //We have to use Draw since we have a target device and IC. + hr=m_pIViewObject2->Draw(dwAspect, -1, NULL, ptd, hIC, hDC, NULL, &rcl, NULL, 0); + //hr=m_pIViewObject2->Draw(dwAspect, -1, NULL, ptd, hIC, hDC, &rcl, NULL, NULL, 0); + + //End CHAPTER17MOD + + /* + * If Draw failed, then perhaps it couldn't work for the device, + * so try good old OleDraw as a last resort. The code will + * generally be OLE_E_BLANK. + */ + if (FAILED(hr)) + OleDraw(m_pObj, dwAspect, hDC, &rc); + //OleDraw(m_pObj, m_fe.dwAspect, hDC, &rc); + + //CHAPTER17MOD + if (!fPrinter + && (TENANTSTATE_SELECTED | TENANTSTATE_OPEN) & m_dwState) + { + /* + * Draw sizing handles to show the selection state. We + * convert things to MM_TEXT since that's what this + * function expects. + */ + RectConvertMappings(&rc, NULL, TRUE); + uMM=SetMapMode(hDC, MM_TEXT); + + if (TENANTSTATE_SELECTED & m_dwState) + { + UIDrawHandles(&rc, hDC, UI_HANDLES_INSIDE + | UI_HANDLES_NOBORDER | UI_HANDLES_USEINVERSE + , CXYHANDLE, TRUE); + } + + if (TENANTSTATE_OPEN & m_dwState) + UIDrawShading(&rc, hDC, UI_SHADE_FULLRECT, 0); + + uMM=SetMapMode(hDC, uMM); + } + //End CHAPTER17MOD + + return; + } + + + + + +/* + * CSO_Cont::Repaint + * CSO_Cont::Invalidate + * + * Purpose: + * Repaints the tenant where it lies or invalidates its area + * for later repainting. + * + * Parameters: + * None + * + * Return Value: + * None + */ + +void CSO_Cont::Repaint(void) + { + + //CHAPTER17MOD + /* + * We might be asked to repaint from + * IOleClientSite::OnShowWindow after we've switched pages if + * our server was running. This check on m_cOpens prevents that. + */ + if (0==m_cOpens || !m_fRepaintEnabled) + return; + //End CHAPTER17MOD + + /* MM ??? + hDC=GetDC(m_hWnd); + SetRect(&rc, m_pPG->m_xPos, m_pPG->m_yPos, 0, 0); + RectConvertMappings(&rc, NULL, FALSE); + + SetMapMode(hDC, MM_LOMETRIC); + Draw(hDC, NULL, NULL, rc.left, rc.top, FALSE, FALSE); + + ReleaseDC(m_hWnd, hDC); + */ + return; + } + + +void CSO_Cont::Invalidate(void) + { + RECTL rcl; + RECT rc; + + RectGet(&rcl, TRUE); + RECTFROMRECTL(rc, rcl); + + /* MMM ??? + OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos); + InvalidateRect(m_hWnd, &rc, FALSE); + */ + + return; + } + + + + +//CHAPTER17MOD +/* + * CSO_Cont::ObjectClassFormatAndIcon + * + * Purpose: + * Helper function for CPage::ConvertObject to retrieve necessary + * information about the object. + * + * Parameters: + * pClsID LPCLSID in which to store the CLSID. + * pwFormat LPWORD in which to store the clipboard format + * used. + * ppszType LPTSTR * in which to return a pointer to a + * type string. + * phMetaIcon HGLOBAL * in which to return the metafile + * icon currently in use. + * + * Return Value: + * None + */ + +void CSO_Cont::ObjectClassFormatAndIcon(LPCLSID pClsID + , LPWORD pwFormat, LPTSTR *ppszType, HGLOBAL *phMetaIcon + , LPTSTR *ppszLabel) + { + HRESULT hr; + TCHAR szType[128]; + LPDATAOBJECT pIDataObject; + FORMATETC fe; + STGMEDIUM stm; + + if (TENANTTYPE_EMBEDDEDOBJECT!=m_tType || NULL==m_pIOleObject) + return; + + if (NULL==pClsID || NULL==pwFormat || NULL==ppszType + || NULL==phMetaIcon) + return; + + + /* + * For embedded objects get the real CLSID of the object and + * its format string. If this fails then we can try to ask + * the object, or we can look in the registry. + */ + + hr=ReadClassStg(m_pIStorage, pClsID); + + if (FAILED(hr)) + { + hr=m_pIOleObject->GetUserClassID(pClsID); + + if (FAILED(hr)) + *pClsID=CLSID_NULL; + } + + + hr=StarObject_ReadFmtUserTypeStg(m_pIStorage, pwFormat, ppszType); + + if (FAILED(hr)) + { + *pwFormat=0; + *ppszType=NULL; + + if (StarObject_GetUserTypeOfClass(*pClsID, 0, szType + , sizeof(szType))) + { + *ppszType=StarObject_CopyString(szType); + } + } + + /* + * Try to get the AuxUserType from the registry, using + * the short version (registered under AuxUserType\2). + * If that fails, just copy *ppszType. + */ + *ppszLabel=NULL; + + if (StarObject_GetUserTypeOfClass(*pClsID, 2, szType + , sizeof(szType))) + { + *ppszLabel=StarObject_CopyString(szType); + } + else + *ppszLabel=StarObject_CopyString(*ppszType); + + //Get the icon for this thing, if we're iconic. + *phMetaIcon=NULL; + + hr=m_pObj->QueryInterface(IID_IDataObject + , (PPVOID)&pIDataObject); + + if (SUCCEEDED(hr)) + { + SETFormatEtc(fe, CF_METAFILEPICT, DVASPECT_ICON, NULL + , TYMED_MFPICT, -1); + hr=pIDataObject->GetData(&fe, &stm); + pIDataObject->Release(); + + if (SUCCEEDED(hr)) + *phMetaIcon=stm.hGlobal; + else + *phMetaIcon=OleGetIconOfClass(*pClsID, NULL, TRUE); + } + + return; + } + + + + +/* + * CSO_Cont::SwitchOrUpdateAspect + * + * Purpose: + * Switches between DVASPECT_CONTENT and DVASPECT_ICON + * + * Parameters: + * hMetaIcon HGLOBAL to the new icon if we're changing the + * icon or switching to DVASPECT_ICON. NULL to + * change back to content. + * fPreserve WIN_BOOL indicating if we're to preserve the old + * aspect after changing. + * + * Return Value: + * WIN_BOOL TRUE if anything changed, FALSE otherwise. + */ + +WIN_BOOL CSO_Cont::SwitchOrUpdateAspect(HGLOBAL hMetaIcon + , WIN_BOOL fPreserve) + { + HRESULT hr; + WIN_BOOL fUpdate=FALSE; + + //Nothing to do if we're content already and there's no icon. + //if (NULL==hMetaIcon && DVASPECT_CONTENT==m_fe.dwAspect) + if (NULL==hMetaIcon && DVASPECT_CONTENT==dwAspect) + return FALSE; + + //If we're iconic already, just cache the new icon + //if (NULL!=hMetaIcon && DVASPECT_ICON==m_fe.dwAspect) + if (NULL!=hMetaIcon && DVASPECT_ICON==dwAspect) + hr=StarObject_SetIconInCache(m_pIOleObject, hMetaIcon); + else + { + //Otherwise, switch between iconic and content. + dwAspect=(NULL==hMetaIcon) ? DVASPECT_CONTENT : DVASPECT_ICON; + + /* + * Switch between aspects, where dwAspect has the new one + * and m_fe.dwAspect will be changed in the process. + */ + hr=StarObject_SwitchDisplayAspect(m_pIOleObject + , &dwAspect, dwAspect, hMetaIcon, !fPreserve + //, &m_fe.dwAspect, dwAspect, hMetaIcon, !fPreserve + , TRUE, m_pImpIAdviseSink, &fUpdate); + + if (SUCCEEDED(hr)) + { + //Update MiscStatus for the new aspect + m_pIOleObject->GetMiscStatus(dwAspect, &m_grfMisc); + //m_pIOleObject->GetMiscStatus(m_fe.dwAspect, &m_grfMisc); + + if (fUpdate) + m_pIOleObject->Update(); //This repaints. + } + } + + //If we switched, update our extents. + if (SUCCEEDED(hr)) + { + SIZEL szl; + + m_pIOleObject->GetExtent(dwAspect, &szl); + //m_pIOleObject->GetExtent(m_fe.dwAspect, &szl); + + if (0 > szl.cy) + szl.cy=-szl.cy; + + //Convert HIMETRIC absolute units to our LOMETRIC mapping + //if (0!=szl.cx && 0!=szl.cy) + // SETSIZEL(szl, szl.cx/10, -szl.cy/10); + + Invalidate(); //Remove old aspect + SizeSet(&szl, FALSE, FALSE); //Change size + Repaint(); //Paint the new one + } + + return SUCCEEDED(hr); + } + + + +/* + * CSO_Cont::EnableRepaint + * + * Purpose: + * Toggles whether the Repaint function does anything. This + * is used during conversion/emulation of an object to disable + * repaints until the new object can be given the proper extents. + * + * Parameters: + * fEnable TRUE to enable repaints, FALSE to disable. + * + * Return Value: + * None + */ + +void CSO_Cont::EnableRepaint(WIN_BOOL fEnable) + { + m_fRepaintEnabled=fEnable; + return; + } +//End CHAPTER17MOD + + + + + + + + +/* + * CSO_Cont::ObjectGet + * + * Purpose: + * Retrieves the LPUNKNOWN of the object in use by this tenant + * + * Parameters: + * ppUnk LPUNKNOWN * in which to return the object + * pointer. + * + * Return Value: + * None + */ + +void CSO_Cont::ObjectGet(LPUNKNOWN *ppUnk) + { + if (NULL!=ppUnk) + { + *ppUnk=m_pObj; + m_pObj->AddRef(); + } + + return; + } + + + + + +/* + * CSO_Cont::FormatEtcGet + * + * Purpose: + * Retrieves the FORMATETC in use by this tenant + * + * Parameters: + * pFE LPFORMATETC in which to store the information. + * fPresentation WIN_BOOL indicating if we want the real format or + * that of the presentation. + * + * Return Value: + * None + */ + +void CSO_Cont::FormatEtcGet(LPFORMATETC pFE, WIN_BOOL fPresentation) + { + if (NULL!=pFE) + { + SETDefFormatEtc(*pFE, 0, TYMED_NULL); + //*pFE=m_fe; + + //CHAPTER17MOD + //If there is no format, use metafile (for embedded objects) + if (fPresentation || 0==pFE->cfFormat) + { + //Don't mess with dwAspect; might be icon or content. + pFE->cfFormat=CF_METAFILEPICT; + pFE->tymed=TYMED_MFPICT; + } + //End CHAPTER17MOD + } + + return; + } + + + + +WIN_BOOL CSO_Cont::GetExtent(LPSIZEL pszl) +{ + //SETSIZEL((*pszl), 2*LOMETRIC_PER_INCH, 2*LOMETRIC_PER_INCH); + SETSIZEL((*pszl), 2*HIMETRIC_PER_INCH, 2*HIMETRIC_PER_INCH); + SIZEL szl = SIZEL(); + HRESULT hr=ResultFromScode(E_FAIL); + + //Try IViewObject2 first, then IOleObject as a backup. + if (NULL!=m_pIViewObject2) + { + hr = m_pIViewObject2->GetExtent(dwAspect, -1, NULL, &szl); + //hr=m_pIViewObject2->GetExtent(m_fe.dwAspect, -1, NULL, &szl); + } + else + { + if (NULL!=m_pIOleObject) + hr = m_pIOleObject->GetExtent(dwAspect, &szl); + //hr=m_pIOleObject->GetExtent(m_fe.dwAspect, &szl); + } + if (SUCCEEDED(hr)) + { + *pszl = szl; + //Convert HIMETRIC to our LOMETRIC mapping + //SETSIZEL((*pszl), szl.cx/10, szl.cy/10); + } + + return SUCCEEDED( hr ); +} + +/* + * CSO_Cont::SizeGet + * CSO_Cont::SizeSet + * CSO_Cont::RectGet + * CSO_Cont::RectSet + * + * Purpose: + * Returns or sets the size/position of the object contained here. + * + * Parameters: + * pszl/prcl LPSIZEL (Size) or LPRECTL (Rect) with the + * extents of interest. In Get situations, + * this will receive the extents; in Set it + * contains the extents. + * fDevice WIN_BOOL indicating that pszl/prcl is expressed + * in device units. Otherwise it's LOMETRIC. + * fInformObj (Set Only) WIN_BOOL indicating if we need to inform + * the object all. + * + * Return Value: + * None + */ + +void CSO_Cont::SizeGet(LPSIZEL pszl, WIN_BOOL fDevice) + { + if (!fDevice) + { + pszl->cx=m_rcl.right-m_rcl.left; + pszl->cy=m_rcl.bottom-m_rcl.top; + } + else + { + RECT rc; + + SetRect(&rc, (int)(m_rcl.right-m_rcl.left) + , (int)(m_rcl.bottom-m_rcl.top), 0, 0); + + RectConvertMappings(&rc, NULL, TRUE); + + pszl->cx=(long)rc.left; + pszl->cy=(long)rc.top; + } + + return; + } + +//CHAPTER17MOD +void CSO_Cont::SizeSet(LPSIZEL pszl, WIN_BOOL fDevice, WIN_BOOL fInformObj) +//End CHAPTER17MOD + { + SIZEL szl; + + if (!fDevice) + { + szl=*pszl; + m_rcl.right =pszl->cx+m_rcl.left; + m_rcl.bottom=pszl->cy+m_rcl.top; + } + else + { + RECT rc; + + SetRect(&rc, (int)pszl->cx, (int)pszl->cy, 0, 0); + RectConvertMappings(&rc, NULL, FALSE); + + m_rcl.right =(long)rc.left+m_rcl.left; + m_rcl.bottom=(long)rc.top+m_rcl.top; + + SETSIZEL(szl, (long)rc.left, (long)rc.top); + } + + + //Tell OLE that this object was resized. + //CHAPTER17MOD + if (NULL!=m_pIOleObject && fInformObj) + { + HRESULT hr; + WIN_BOOL fRun=FALSE; + + //Convert our LOMETRIC into HIMETRIC by *=10 + //szl.cx*=10; + //szl.cy*=-10; //Our size is stored negative. + if( szl.cy < 0 ) + szl.cy *= -1; + + /* + * If the MiscStatus bit of OLEMISC_RECOMPOSEONRESIZE + * is set, then we need to run the object before calling + * SetExtent to make sure it has a real chance to + * re-render the object. We have to update and close + * the object as well after this happens. + */ + + if (OLEMISC_RECOMPOSEONRESIZE & m_grfMisc) + { + if (!OleIsRunning(m_pIOleObject)) + { + OleRun(m_pIOleObject); + fRun=TRUE; + } + } + + hr=m_pIOleObject->SetExtent(dwAspect, &szl); + //hr=m_pIOleObject->SetExtent(m_fe.dwAspect, &szl); + + /* + * If the object is not running and it does not have + * RECOMPOSEONRESIZE, then SetExtent fails. Make + * sure that we call SetExtent again (by just calling + * SizeSet here again) when we next run the object. + */ + if (SUCCEEDED(hr)) + { + m_fSetExtent=FALSE; + + if (fRun) + { + m_pIOleObject->Update(); + m_pIOleObject->Close(OLECLOSE_SAVEIFDIRTY); + } + } + else + { + if (OLE_E_NOTRUNNING==GetScode(hr)) + m_fSetExtent=TRUE; + } + } + //End CHAPTER17MOD + + return; + } + + +void CSO_Cont::RectGet(LPRECTL prcl, WIN_BOOL fDevice) + { + if (!fDevice) + *prcl=m_rcl; + else + { + RECT rc; + + RECTFROMRECTL(rc, m_rcl); + RectConvertMappings(&rc, NULL, TRUE); + RECTLFROMRECT(*prcl, rc); + } + + return; + } + + +//CHAPTER17MOD +void CSO_Cont::RectSet(LPRECTL prcl, WIN_BOOL fDevice, WIN_BOOL fInformObj) +//End CHAPTER17MOD + { + SIZEL szl; + LONG cx, cy; + + cx=m_rcl.right-m_rcl.left; + cy=m_rcl.bottom-m_rcl.top; + + if (!fDevice) + m_rcl=*prcl; + else + { + RECT rc; + + RECTFROMRECTL(rc, *prcl); + RectConvertMappings(&rc, NULL, FALSE); + RECTLFROMRECT(m_rcl, rc); + } + + /* + * Tell ourselves that the size changed, if it did. SizeSet + * will call IOleObject::SetExtent for us. + */ + if ((m_rcl.right-m_rcl.left)!=cx || (m_rcl.bottom-m_rcl.top)!=cy) + { + SETSIZEL(szl, m_rcl.right-m_rcl.left, m_rcl.bottom-m_rcl.top); + //CHAPTER17MOD + SizeSet(&szl, FALSE, fInformObj); + //End CHAPTER17MOD + } + + return; + } + + + + + + + +/* + * CSO_Cont::CreateStatic + * (Protected) + * + * Purpose: + * Creates a new static bitmap or metafile object for this tenant + * using a freeloading method allowing us to specify exactly which + * type of data we want to paste since OleCreateStaticFromData + * doesn't. + * + * Parameters: + * pIDataObject LPDATAOBJECT from which to paste. + * pFE LPFORMATETC describing the format to paste. + * ppObj LPUNKNOWN * into which we store the + * object pointer. + * + * Return Value: + * HRESULT NOERROR on success, error code otherwise. + */ + +HRESULT CSO_Cont::CreateStatic(LPDATAOBJECT pIDataObject + , LPFORMATETC pFE, LPUNKNOWN *ppObj) + { + HRESULT hr; + STGMEDIUM stm; + LPUNKNOWN pIUnknown; + LPOLECACHE pIOleCache; + LPPERSISTSTORAGE pIPersistStorage; + CLSID clsID; + + *ppObj=NULL; + + //Try to get the data desired as specified in pFE->cfFormat + hr=pIDataObject->GetData(pFE, &stm); + + if (FAILED(hr)) + return hr; + + //Create the object to handle this data. + if (CF_METAFILEPICT==pFE->cfFormat) + clsID=CLSID_Picture_Metafile; + else + clsID=CLSID_Picture_Dib; + + hr=CreateDataCache(NULL, clsID, IID_IUnknown + , (PPVOID)&pIUnknown); + + if (FAILED(hr)) + { + ReleaseStgMedium(&stm); + return hr; + } + + m_clsID=clsID; + + //Stuff the data into the object + pIUnknown->QueryInterface(IID_IPersistStorage + , (PPVOID)&pIPersistStorage); + pIPersistStorage->InitNew(m_pIStorage); + + //Now that we have the cache object, shove the data into it. + pIUnknown->QueryInterface(IID_IOleCache, (PPVOID)&pIOleCache); + pIOleCache->Cache(pFE, ADVF_PRIMEFIRST, NULL); + + hr=pIOleCache->SetData(pFE, &stm, TRUE); + pIOleCache->Release(); + + //Insure there is a persistent copy on the disk + WriteClassStg(m_pIStorage, m_clsID); + pIPersistStorage->Save(m_pIStorage, TRUE); + pIPersistStorage->SaveCompleted(NULL); + pIPersistStorage->Release(); + + //The cache owns this now. + ReleaseStgMedium(&stm); + + if (FAILED(hr)) + pIUnknown->Release(); + else + *ppObj=pIUnknown; + + return hr; + } + +CLSID CSO_Cont::GetCLSID() +{ + if ( m_clsID == GUID_NULL ) + { + LPPERSIST pIPS; + m_pObj->QueryInterface(IID_IPersist, (PPVOID)&pIPS); + pIPS->GetClassID( &m_clsID ); + } + + return m_clsID; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |