/*
*********************************************************************
*
*	The Essence of OLE
*
*	Source code sample
*
*	Copyright (c) 1996, Rolling Thunder Computing, Ipswich MA
*
*	e-mail: essence@rollthunder.com
*	CompuServe: 73540,3430
*	Web: http://www.rollthunder.com
*
*	File Name: CFILETEXTDATA.CPP
*
*	Purpose: IDataObject interface for transfer text data from server to client
*
*********************************************************************
*/

#include <windows.h>
#include "cperfile.h"
#include "cfiletextdata.h"
#include "cenum.h"

FORMATETC feArray []= {
						{ CF_TEXT, NULL, DVASPECT_CONTENT,  -1, TYMED_HGLOBAL },
					 	{ CF_METAFILEPICT, NULL, DVASPECT_CONTENT,  -1, TYMED_MFPICT }								 
					  };
/*
constructor/destructor 
*/

CFileTextData::CFileTextData( )
{
	m_wFileName [0] = 0x0000 ;
	m_pFileMoniker = NULL ;
	m_dwRegisterROT	 = 0 ;

    return;
}

CFileTextData::CFileTextData (char *cp, int length)
{
	m_length = length ;
	m_cp = (char *)GlobalAlloc (GMEM_FIXED, m_length+1) ;
	lstrcpyn (m_cp, cp, m_length) ;
}


CFileTextData::~CFileTextData(void)
{

/*
Remove ourselves from the running object table.
*/
	if (m_dwRegisterROT != 0)
	{
		LPRUNNINGOBJECTTABLE pROT ;

		GetRunningObjectTable (0, &pROT) ;				
		pROT->Revoke (m_dwRegisterROT) ;
		pROT->Release ( ) ;
	}
/*
Release moniker
*/
	if (m_pFileMoniker)
	{
		m_pFileMoniker->Release ( ) ;
	}

/*
Free data storage 
*/
	GlobalFree (m_cp) ;

    return;
}


/*
GetData Method.  Caller is asking if we can supply data in a given 
format and medium
*/

STDMETHODIMP CFileTextData::GetData (LPFORMATETC lpfe, LPSTGMEDIUM lpstg) 
{

/*
We support text format, transferred through a global, with aspect
content. Allocate a new global, copy our text into it, and fill in the 
elements of the STGMEDIUM structure that we were passed
*/

	if (lpfe->cfFormat == CF_TEXT 
		&& lpfe->tymed == TYMED_HGLOBAL
		&& lpfe->dwAspect == DVASPECT_CONTENT)
	{
		LPSTR cpout ; 
		
		cpout = (LPSTR) GlobalAlloc(GMEM_FIXED, m_length);
		if (!cpout)
		{
    		return E_OUTOFMEMORY ;
		}	                                       
		
		lstrcpy (cpout, m_cp) ;
	    
	    lpstg->tymed = TYMED_HGLOBAL ;
    	lpstg->hGlobal = (HGLOBAL) cpout ;
	   	lpstg->pUnkForRelease = NULL ;
    	
    	return S_OK ;

	}

/*
We also support the metafile format (in tasteful colors of yellow on 
green.
*/

	else if (lpfe->cfFormat == CF_METAFILEPICT
		&& lpfe->tymed == TYMED_MFPICT
		&& lpfe->dwAspect == DVASPECT_CONTENT)
	{
		HMETAFILE hMF ; HDC hDC ;

/*
Create a DC mapped to a metafile, draw our text on the DC, then close 
the DC to convert it into a memory metafile
*/
		
		hDC = CreateMetaFile (NULL) ;
		

		SetBkColor (hDC, RGB (0, 255, 0)) ;
		SetTextColor (hDC, RGB (255, 255, 0)) ;
		TextOut (hDC, 0, 0, m_cp, m_length-1) ;
		
		hMF = CloseMetaFile (hDC) ;

/*
Allocate a METAFILEPICT structure to described the picture, fill in 
its elements, then fill in the elements of STGMEDIUM structure to 
return data to caller.
*/

		METAFILEPICT *pMF = (METAFILEPICT *) GlobalAlloc (GPTR, 
			sizeof (METAFILEPICT));

		pMF->hMF = hMF ;
		pMF->mm = MM_TEXT ;
		pMF->xExt = 100 ;
		pMF->yExt = 100 ;

		lpstg->tymed = TYMED_MFPICT ;
		lpstg->hGlobal = pMF ;
		lpstg->pUnkForRelease = NULL ;

    	return S_OK ;

	}

/*
User asked for a format that we couldn't supply.  Return error code.
*/
	
	return DATA_E_FORMATETC ;
}



STDMETHODIMP CFileTextData::QueryGetData (LPFORMATETC lpfe) 
{

/*
We'll give you text, transferred through a global, with aspect
content.  If the user is asking for this, return success code.
*/

	if (lpfe->cfFormat == CF_TEXT 
		&& lpfe->tymed == TYMED_HGLOBAL
		&& lpfe->dwAspect == DVASPECT_CONTENT)
	{
		return S_OK ;
	}

/*
Or we'll give the the same text drawn in a metafile, also with aspect content.  Return success code.
*/

	else if (lpfe->cfFormat == CF_METAFILEPICT
		&& lpfe->tymed == TYMED_MFPICT
		&& lpfe->dwAspect == DVASPECT_CONTENT)
	{
		return S_OK ;
	}
	
/*
But we won't give you anything else
*/
	return DATA_E_FORMATETC ;
    
}

STDMETHODIMP CFileTextData::EnumFormatEtc (DWORD dwDir, LPENUMFORMATETC * lpEnum) 
{
	*lpEnum = (LPENUMFORMATETC) new CEnumerator ((LPDATAOBJECT)this, feArray, 2, 
		sizeof (FORMATETC), IID_IEnumFORMATETC) ;

	if (*lpEnum == NULL)	
	{
		return E_FAIL ;
	}
	
	return S_OK ;
}

/*
Unimplemented members
*/

STDMETHODIMP CFileTextData::GetDataHere (LPFORMATETC lpfe, LPSTGMEDIUM lpst)
{
	return E_NOTIMPL ;
}

STDMETHODIMP CFileTextData::GetCanonicalFormatEtc (LPFORMATETC lpout, LPFORMATETC lpin)
{
	return E_NOTIMPL ;
}

STDMETHODIMP CFileTextData::SetData (LPFORMATETC lpfe, STGMEDIUM * lpst, BOOL fRelease)
{
	return E_NOTIMPL ;
}

STDMETHODIMP CFileTextData::DAdvise (FORMATETC * lpfe, DWORD dw, LPADVISESINK lpas, 
	DWORD FAR* lpdw) 
{
	return E_NOTIMPL ;
}

STDMETHODIMP CFileTextData::DUnadvise  (DWORD dw)
{
	return E_NOTIMPL ;
}

STDMETHODIMP CFileTextData::EnumDAdvise  (LPENUMSTATDATA * lpen)
{
	*lpen = NULL ;
	return E_NOTIMPL ;
}


HRESULT CFileTextData::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
    if (riid == IID_IUnknown || riid == IID_IDataObject)
    {
        *ppv = (LPDATAOBJECT)this;  
        AddRef( );
        return S_OK ;
    }
	else if (riid == IID_IPersistFile || riid == IID_IPersist)
	{
		*ppv = (LPPERSISTFILE) this ;
		AddRef ( ) ;
		return S_OK ;
	}
	else if (riid == IID_IOleItemContainer)
	{
		*ppv = (LPOLEITEMCONTAINER) this ;
		AddRef( ) ;
		return S_OK ;
	}
    else
    {
    	*ppv = NULL;       
    	return E_NOINTERFACE ;
    }
}


STDMETHODIMP_(ULONG) CFileTextData::AddRef(void)
{
    m_RefCount ++ ;
    return m_RefCount ;
}


STDMETHODIMP_(ULONG) CFileTextData::Release(void)
{
    
    m_RefCount -- ;
    
    if (m_RefCount == 0L)
    {
        delete this;
    }	return 0 ;

    return m_RefCount ;
}
