OLEOBJ.C

/* 
* OLEOBJ.C
*
* Contains all callback functions in the OLEOBJECTVTBL struture:
* ObjDoVerb
* ObjEnumFormats
* ObjGetData
* ObjQueryProtocol
* ObjRelease
* ObjSetBounds
* ObjSetColorScheme
* ObjSetData
* ObjSetTargetDevice
* ObjShow
*
* There are additional callbacks in the OLEOBJECTVTBL.
* Also contains PObjectAllocate, a constructor for the object.
*
* Copyright(c) Microsoft Corp. 1992-1994 All Rights Reserved
* Win32 version, January 1994
*/

#ifdef MAKEOLESERVER

#include <windows.h>
#include <ole.h>
#include "cosmo.h"
#include "oleglobl.h"
#include "oleinst.h" //OBJVERB_* defines for ObjDoVerb

/*
* PObjectAllocate
*
* Purpose:
* Allocates a COSMOOBJECT structure and sets the defaults in its fields.
* Used from DocGetObject.
*
* Parameters:
* pVtblObj LPOLESERVERDOCVTBL used to initialize the pvtbl field.
*
* Return Value:
* LPCOSMOOBJECT Pointer to the allocated structure in local memory.
* The hMem field will contain a handle to the structure
* to pass to LocalFree.
*/

LPCOSMOOBJECT WINAPI PObjectAllocate(LPOLEOBJECTVTBL pVtblObj)
{
HLOCAL hMem;
LPCOSMOOBJECT pObj;

hMem=LocalAlloc(LPTR, sizeof(COSMOOBJECT));
pObj=(LPCOSMOOBJECT)(PSTR)hMem;

//Initialize the object.
pObj->hMem=hMem;
pObj->pvtbl=pVtblObj;
pObj->fRelease=TRUE;

return pObj;
}




/*
* ObjDoVerb
*
* Purpose:
* Performs actions on an object when the user opens an object
* according to the verb given.
*
* Parameters:
* pObj LPCOSMOOBJECT specifying the object affected.
* iVerb UINT index to the verb chosen, zero based.
* fShow BOOL--TRUE if the application should show
* itself with ShowWindow. FALSE means no change.
* fFocus BOOL--TRUE if the server should get the focus.
*
* Return Value:
* OLESTATUS OLE_OK if all is well, otherwise an OLE_* error value.
*/

OLESTATUS WINAPI ObjDoVerb(LPCOSMOOBJECT pObj, UINT iVerb
, BOOL fShow, BOOL fFocus)
{
/*
* 1. Execute the verb.
* a. For a 'Play' verb, a server does not generally show
* its window or affect the focus.
*
* b. For an 'Edit' verb, show the server's window and the
* object if fShow is TRUE, and take the focus if fFocus
* is TRUE. An ideal way to accomplish this is to call
* the ObjShow method through the OLEOBJECTVTBL since that
* method will handle showing the object and taking the
* focus itself.
*
* c. An 'Open' verb is not clearly defined; depending on the
* application it may mean the same as 'Play' or 'Edit.'
* The Cosmo server, if it had an 'Open' verb, would treat
* it like 'Edit.'
*
* 2. Return OLE_OK if the verb was successfully executed, otherwise
* OLE_ERROR_DOVERB.
*/

switch (iVerb)
{
case OBJVERB_EDIT:
/*
* On edit, simply show yourself and expect a SetData.
* Best strategy is to use the Show method for this
* object if necessary, reducing redundancy.
*/
if (fShow)
return (pObj->pvtbl->Show)((LPOLEOBJECT)pObj, fShow);

//Return OLE_OK
break;


case OBJVERB_PLAY:
//Unsupported at this time.
return OLE_ERROR_DOVERB;

default:
return OLE_ERROR_DOVERB;
}

return OLE_OK;
}





/*
* ObjEnumFormats
*
* Purpose:
* Requests the server to produce the 'next' supported clipboard
* format. Each format is returned in sequence until the terminator
* (a NULL) is returned.
*
* Parameters:
* pObj LPCOSMOOBJECT specifying the object affected.
* cf OLECLIPFORMAT the last clipboard format returned by
* this function. 0 indicates the first.
*
* Return Value:
* OLESTATUS OLE_OK if all is well, otherwise an OLE_* error value.
*/

OLECLIPFORMAT WINAPI ObjEnumFormats(LPCOSMOOBJECT pObj, OLECLIPFORMAT cf)
{
/*
* 1. Depending on cf, return the 'next' clipboard format in which
* the server can render the object's data.
* 2. If there are no more supported formats after the format in cf,
* return NULL.
*
* We must use multiple if's instead of a switch statement because
* all the cf* values are not constants.
*/

if (0==cf)
return pOLE->cfNative;

if (pOLE->cfNative==cf)
return pOLE->cfOwnerLink;

if (pOLE->cfOwnerLink==cf)
return CF_METAFILEPICT;

if (CF_METAFILEPICT==cf)
return CF_BITMAP;

if (CF_BITMAP==cf)
return pOLE->cfObjectLink;

//This IF is here just to be explicit.
if (pOLE->cfObjectLink==cf)
return 0;

return 0;
}






/*
* ObjGetData
*
* Purpose:
* Retrieves data from the object in a specified format, where the
* server should allocate memory (GlobalAlloc with GMEM_DDESHARE),
* fill the memory, and return the handle.
*
* Parameters:
* pObj LPCOSMOOBJECT specifying the object affected.
* cf OLECLIPFORMAT format to return data in, may be "Native."
* phData HGLOBAL FAR * in which to store the allocated handle.
*
* Return Value:
* OLESTATUS OLE_OK if all is well, otherwise an OLE_* error value.
*/

OLESTATUS WINAPI ObjGetData(LPCOSMOOBJECT pObj, OLECLIPFORMAT cf
, HGLOBAL FAR * phData)
{
HGLOBAL hMem;

/*
* 1. Allocate the requested data throguh GlobalAlloc (with
* GMEM_MOVEABLE and GMEM_DDESHARE). The exception is data for
* CF_BITMAP which uses a call like CreateBitmap.
* 2. Lock and fill the memory with the appropriate data.
* 3. Unlock the memory and store the handle in *phData.
* 4. Return OLE_OK if successful, OLE_ERROR_MEMORY otherwise.
*/

//Return Native, metafile, or bitmap as requested.
if (pOLE->cfNative==cf)
hMem=HGetPolyline(pGlob->hWndPolyline);

if (CF_METAFILEPICT==cf)
hMem=HGetMetafilePict(pGlob->hWndPolyline);

if (CF_BITMAP==cf)
hMem=HGetBitmap(pGlob->hWndPolyline);


//Use filename
if (pOLE->cfObjectLink==cf)
hMem=HLinkConstruct(rgpsz[IDS_CLASSCOSMO], "", "");

/*
* Even though this is exactly like ObjectLink, this is coded as
* a separate case just in case it changes in the future.
*/
if (pOLE->cfOwnerLink==cf)
hMem=HLinkConstruct(rgpsz[IDS_CLASSCOSMO], "", "");


if (NULL==hMem)
return OLE_ERROR_MEMORY;

*phData=hMem;
return OLE_OK;
}





/*
* ObjQueryProtocol
*
* Purpose:
* Returns a pointer to an COSMOOBJECT with the appropriate VTBL for
* the protocol, either StdFileEditing or StdExecute. Returns NULL
* if that protocol is not supported.
*
* Parameters:
* pObj LPCOSMOOBJECT specifying the object affected.
* pszProtocol OLE_LPCSTR, the protocol name.
*
* Return Value:
* OLESTATUS OLE_OK if all is well, otherwise an OLE_* error value.
*/

LPVOID WINAPI ObjQueryProtocol(LPCOSMOOBJECT pObj, OLE_LPCSTR pszProtocol)
{

/*
* 1. If the protocol in pszProtocol is supported, return a pointer
* to an object that contains an appropriate VTBL fot that protocol,
* such as the pObj passed to this method.
* 2. If the protocol is not supported, return NULL.
*/

//Check if OLESVR is asking for "StdFileEditing"
if (0==lstrcmp(pszProtocol, rgpsz[IDS_STDFILEEDITING]))
return (LPVOID)pObj;

return (LPVOID)NULL;
}






/*
* ObjRelease
*
* Purpose:
* Notifies a server that is can free any resources associated with an
* object.
*
* Parameters:
* pObj LPCOSMOOBJECT specifying the object affected.
*
* Return Value:
* OLESTATUS OLE_OK if all is well, otherwise an OLE_* error value.
*/

OLESTATUS WINAPI ObjRelease(LPCOSMOOBJECT pObj)
{
/*
* 1. Free any resources allocated for this object, but
* DO NOT free the OLEOBJECT structure itself.
* 2. Set a flag to indicate that Release has been called.
* 3. NULL any saved LPOLECLIENT stores in the OLEOBJECT structure.
* 4. Return OLE_OK if successful, OLE_ERROR_GENERIC otherwise.
*
* Do not use the Release method to free the memory containing
* the object since you still need to use its pClient and fRelease.
* This method simply notifies the object that no one is using it
* anymore so we don't try to send notifications.
*/

pObj->fRelease=TRUE;
pObj->pClient=NULL;
return OLE_OK;
}





/*
* ObjSetBounds
*
* Purpose:
* Specifies a new boundary rectangle for the object in MM_HIMETRIC
* units. Only useful for embedded objects since a linked object
* depends on the file loaded.
*
* Parameters:
* pObj LPCOSMOOBJECT specifying the object affected.
* pRect LPRECT containing the new bounds.
*
* Return Value:
* OLESTATUS OLE_OK if all is well, otherwise an OLE_* error value.
*/

OLESTATUS WINAPI ObjSetBounds(LPCOSMOOBJECT pObj, OLE_CONST RECT FAR *pRect)
{
//Unused in OLE1.x
return OLE_OK;
}




/*
* ObjSetColorScheme
*
* Purpose:
* Provides a color scheme that the client application recommends for
* rendering graphical data.
*
* Parameters:
* pDoc LPCOSMOOBJECT specifying the object affected.
* pPal LPLOGPALETTE describing the recommended palette.
*
* Return Value:
* OLESTATUS OLE_OK if all is well, otherwise an OLE_* error value.
*/

OLESTATUS WINAPI ObjSetColorScheme(LPCOSMOOBJECT pObj
, OLE_CONST LOGPALETTE FAR *pPal)
{
/*
* Servers are not required to use this palette. The LPLOGPALETTE
* only is a convenient structure to contain the color scheme; IT DOES
* not REPRESENT A PALETTE IN STRICT TERMS! Do NOT call CreatePalette
* and try to realize it.
*
* The color scheme contained in the LOGPALETTE structure contains
* a number of colors where the first color is the suggested foreground,
* the second the suggested background, then the first HALF of those
* remaining are suggested fill colors and the last half suggested
* line colors. If there are an odd number of colors, give the extra
* color to the fill colors, that is, there is one less line color than
* fill colors.
*/

return OLE_ERROR_PALETTE;
}






/*
* ObjSetData
*
* Purpose:
* Instructs the object to take the given data as current and copy it
* to the object's internal data, use when a client opens an embedded
* object or if the client calls OleSetData.
*
* *NOTE: This function MUST be supported even if the registration
* database does not contain an entry for SetDataFormats for
* this server, because the callback is still used when opening
* an embedded object for editing.
*
* Parameters:
* pObj LPCOSMOOBJECT specifying the object affected.
* cf OLECLIPFORMAT format to return data in, may be "Native."
* hData HGLOBAL to memory containing the data.
*
* Return Value:
* OLESTATUS OLE_OK if all is well, otherwise an OLE_* error value.
*/

OLESTATUS WINAPI ObjSetData(LPCOSMOOBJECT pObj, OLECLIPFORMAT cf
, HGLOBAL hData)
{
LPPOLYLINE lppl;

/*
* 1. If the data format is not supported, return OLE_ERROR_FORMAT.
* 2. Attempt to GlobalLock the memory to get a pointer to the data.
* If GlobalLock returns NULL, return OLE_ERROR_MEMORY.
* 3. Copy the data to the object identified by pObj.
* 4. Unlock and GlobalFree the data handle. The ObjSetData method
* is responsible for the memory.
* 5. Return OLE_OK.
*/

//Check if we were given Native data. We don't support anything else.
if (pOLE->cfNative!=cf)
return OLE_ERROR_FORMAT;

lppl=(LPPOLYLINE)GlobalLock(hData);

/*
* CHECK the return from GlobalLock since we don't know where this
* handle has been.
*/
if (NULL==lppl)
return OLE_ERROR_MEMORY;

//Set the data through the editing window.
SendMessage(pGlob->hWndPolyline, PLM_POLYLINESET, TRUE, (LONG)lppl);

//Make sure we are not dirty--no updating is yet necessary.
FDirtySet(FALSE);

//Server is responsible for freeing the data.
GlobalUnlock(hData);
GlobalFree(hData);
return OLE_OK;
}






/*
* ObjSetTargetDevice
*
* Purpose:
* Communicates information from the client application to the server
* about the device on which the object is drawn.
*
* Parameters:
* pObj LPCOSMOOBJECT specifying the object affected.
* hData HGLOBAL containing a STDTARGETDEVICE structure.
*
* Return Value:
* OLESTATUS OLE_OK if all is well, otherwise an OLE_* error value.
*/

OLESTATUS WINAPI ObjSetTargetDevice(LPCOSMOOBJECT pObj, HGLOBAL hData)
{

/*
* The server is responsible for freeing the the data handle
* once it has finished using that data.
*
* If NULL==hData, then rendering is necessary for the screen.
*/

if (NULL!=hData)
GlobalFree(hData);

return OLE_OK;
}







/*
* ObjShow
*
* Purpose:
* Causes the server to show an object, showing the window and
* scrolling it's client area if necessary.
*
* Parameters:
* pObj LPCOSMOOBJECT specifying the object affected.
* fTakeFocus BOOL: TRUE if the server should get the focus,
* FALSE if not.
*
* Return Value:
* OLESTATUS OLE_OK if all is well, otherwise an OLE_* error value.
*/

OLESTATUS WINAPI ObjShow(LPCOSMOOBJECT pObj, BOOL fTakeFocus)
{
/*
* 1. Show the application window(s) if not already visible.
* 2. Scroll the object identified by pObj into view, if necessary.
* 3. Select the object if possible.
* 4. If fTakeFocus is TRUE, call SetFocus with the main window handle.
* 5. Return OLE_OK if successful, OLE_ERROR_GENERIC otherwise.
*/

//Keep WM_SIZE on the ShowWindow from making us dirty.
pGlob->fNoDirty=TRUE;

//Since we only have one object, we don't care what's in pObj.
ShowWindow(pGlob->hWnd, SW_NORMAL);

pGlob->fNoDirty=FALSE;

if (fTakeFocus)
SetFocus(pGlob->hWnd);

return OLE_OK;
}


#endif //MAKEOLESERVER