496 lines
13 KiB
C
496 lines
13 KiB
C
/****************************** Module Header ******************************\
|
|
* Module Name: DIB.C
|
|
*
|
|
* Handles all API routines for the device independent bitmap sub-dll of
|
|
* the ole dll.
|
|
*
|
|
* Created: Oct-1990
|
|
*
|
|
* Copyright (c) 1990, 1991 Microsoft Corporation
|
|
*
|
|
* History:
|
|
* Srinik, Raor (../../1990,91) Designed, coded
|
|
*
|
|
\***************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include "dll.h"
|
|
#include "pict.h"
|
|
|
|
void FARINTERNAL DibGetExtents (LPSTR, LPPOINT);
|
|
|
|
#pragma alloc_text(_TEXT, DibSaveToStream, DibLoadFromStream, DibStreamRead, GetBytes, PutBytes, PutStrWithLen, DibGetExtents)
|
|
|
|
OLEOBJECTVTBL vtblDIB = {
|
|
|
|
ErrQueryProtocol, // check whether the speced protocol is supported
|
|
|
|
DibRelease, // Release
|
|
ErrShow, // Show
|
|
ErrPlay, // show
|
|
DibGetData, // Get the object data
|
|
ErrSetData, // Set the object data
|
|
ErrSetTargetDevice, //
|
|
|
|
ErrSetBounds, // set viewport bounds
|
|
DibEnumFormat, // enumerate supported formats
|
|
ErrSetColorScheme, //
|
|
DibRelease, // delete
|
|
ErrSetHostNames, //
|
|
|
|
DibSaveToStream, // write to file
|
|
DibClone, // clone object
|
|
ErrCopyFromLink, // Create embedded from Lnk
|
|
|
|
DibEqual, // compares the given objects for data equality
|
|
|
|
DibCopy, // copy to clip
|
|
|
|
DibDraw, // draw the object
|
|
|
|
ErrActivate, // open
|
|
ErrExecute, // excute
|
|
ErrClose, // Stop
|
|
ErrUpdate, // Update
|
|
ErrReconnect, // Reconnect
|
|
|
|
ErrObjectConvert, // convert object to specified type
|
|
|
|
ErrGetUpdateOptions, // update options
|
|
ErrSetUpdateOptions, // update options
|
|
|
|
ObjRename, // Change Object name
|
|
ObjQueryName, // Get current object name
|
|
|
|
ObjQueryType, // Object type
|
|
DibQueryBounds, // QueryBounds
|
|
ObjQuerySize, // Find the size of the object
|
|
ErrQueryOpen, // Query open
|
|
ErrQueryOutOfDate, // query whether object is current
|
|
|
|
ErrQueryRelease, // release related stuff
|
|
ErrQueryRelease,
|
|
ErrQueryRelease,
|
|
|
|
ErrRequestData, // requestdata
|
|
ErrObjectLong, // objectLong
|
|
DibChangeData // change data of the existing object
|
|
};
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL DibRelease (lpobj)
|
|
LPOBJECT_DIB lpobj;
|
|
{
|
|
HOBJECT hobj;
|
|
|
|
if (lpobj->hDIB){
|
|
GlobalFree (lpobj->hDIB);
|
|
lpobj->hDIB = NULL;
|
|
}
|
|
|
|
if (lpobj->head.lhclientdoc)
|
|
DocDeleteObject ((LPOLEOBJECT) lpobj);
|
|
|
|
if (hobj = lpobj->head.hobj){
|
|
lpobj->head.hobj = NULL;
|
|
GlobalUnlock (hobj);
|
|
GlobalFree (hobj);
|
|
}
|
|
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL DibSaveToStream (lpobj, lpstream)
|
|
LPOBJECT_DIB lpobj;
|
|
LPOLESTREAM lpstream;
|
|
{
|
|
LPSTR lpDIBbuf;
|
|
|
|
if (!lpobj->hDIB)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
if (PutBytes (lpstream, (LPSTR) &dwVerToFile, sizeof(LONG)))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
if (PutBytes (lpstream, (LPSTR) &lpobj->head.ctype, sizeof(LONG)))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
if (PutStrWithLen (lpstream, (LPSTR)"DIB"))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
if (PutBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG)))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
if (PutBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG)))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
lpobj->sizeBytes = GlobalSize (lpobj->hDIB);
|
|
if (PutBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(LONG)))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
if (!(lpDIBbuf = GlobalLock (lpobj->hDIB)))
|
|
return OLE_ERROR_MEMORY;
|
|
|
|
if (PutBytes (lpstream, lpDIBbuf, lpobj->sizeBytes))
|
|
return OLE_ERROR_STREAM;
|
|
|
|
GlobalUnlock (lpobj->hDIB);
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL DibClone (lpobjsrc, lpclient, lhclientdoc, lpobjname, lplpobj)
|
|
LPOBJECT_DIB lpobjsrc;
|
|
LPOLECLIENT lpclient;
|
|
LHCLIENTDOC lhclientdoc;
|
|
LPSTR lpobjname;
|
|
LPOBJECT_DIB FAR * lplpobj;
|
|
{
|
|
if (!CheckClientDoc ((LPCLIENTDOC) lhclientdoc))
|
|
return OLE_ERROR_HANDLE;
|
|
|
|
if (!(*lplpobj = DibCreateObject (lpobjsrc->hDIB, lpclient, FALSE,
|
|
lhclientdoc, lpobjname, lpobjsrc->head.ctype)))
|
|
return OLE_ERROR_MEMORY;
|
|
else
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL DibEqual (lpobj1, lpobj2)
|
|
LPOBJECT_DIB lpobj1;
|
|
LPOBJECT_DIB lpobj2;
|
|
{
|
|
if (CmpGlobals (lpobj1->hDIB, lpobj1->hDIB))
|
|
return OLE_OK;
|
|
|
|
return OLE_ERROR_NOT_EQUAL;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL DibCopy (lpobj)
|
|
LPOBJECT_DIB lpobj;
|
|
{
|
|
HANDLE hDIB;
|
|
|
|
if (!lpobj->hDIB)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
if (!(hDIB = DuplicateGlobal (lpobj->hDIB, GMEM_MOVEABLE)))
|
|
return OLE_ERROR_MEMORY;
|
|
|
|
SetClipboardData (CF_DIB, hDIB);
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL DibQueryBounds (lpobj, lpRc)
|
|
LPOBJECT_DIB lpobj;
|
|
LPRECT lpRc;
|
|
{
|
|
Puts("DibQueryBounds");
|
|
|
|
if (!lpobj->hDIB)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
lpRc->left = 0;
|
|
lpRc->top = 0;
|
|
lpRc->right = (int) lpobj->head.cx;
|
|
lpRc->bottom = (int) lpobj->head.cy;
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
|
|
OLECLIPFORMAT FARINTERNAL DibEnumFormat (lpobj, cfFormat)
|
|
LPOBJECT_DIB lpobj;
|
|
OLECLIPFORMAT cfFormat;
|
|
{
|
|
if (!cfFormat)
|
|
return CF_DIB;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL DibGetData (lpobj, cfFormat, lphandle)
|
|
LPOBJECT_DIB lpobj;
|
|
OLECLIPFORMAT cfFormat;
|
|
LPHANDLE lphandle;
|
|
{
|
|
if (cfFormat != CF_DIB)
|
|
return OLE_ERROR_FORMAT;
|
|
|
|
if (!(*lphandle = lpobj->hDIB))
|
|
return OLE_ERROR_BLANK;
|
|
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
|
|
LPOBJECT_DIB FARINTERNAL DibCreateObject (hDIB, lpclient, fDelete, lhclientdoc, lpobjname, objType)
|
|
HANDLE hDIB;
|
|
LPOLECLIENT lpclient;
|
|
BOOL fDelete;
|
|
LHCLIENTDOC lhclientdoc;
|
|
LPSTR lpobjname;
|
|
LONG objType;
|
|
{
|
|
LPOBJECT_DIB lpobj;
|
|
|
|
if (lpobj = DibCreateBlank (lhclientdoc, lpobjname, objType)) {
|
|
if (DibChangeData (lpobj, hDIB, lpclient, fDelete) != OLE_OK) {
|
|
DibRelease (lpobj);
|
|
lpobj = NULL;
|
|
}
|
|
}
|
|
|
|
return lpobj;
|
|
}
|
|
|
|
|
|
|
|
// If the routine fails then the object will be left with it's old data.
|
|
// If fDelete is TRUE, then hNewDIB will be deleted whether the routine
|
|
// is successful or not.
|
|
|
|
OLESTATUS FARINTERNAL DibChangeData (lpobj, hNewDIB, lpclient, fDelete)
|
|
LPOBJECT_DIB lpobj;
|
|
HANDLE hNewDIB;
|
|
LPOLECLIENT lpclient;
|
|
BOOL fDelete;
|
|
{
|
|
BITMAPINFOHEADER bi;
|
|
DWORD dwSize;
|
|
LPBITMAPINFOHEADER lpBi;
|
|
|
|
if (!hNewDIB)
|
|
return OLE_ERROR_BLANK;
|
|
|
|
lpBi = (LPBITMAPINFOHEADER) &bi;
|
|
if (!fDelete) {
|
|
if (!(hNewDIB = DuplicateGlobal (hNewDIB, GMEM_MOVEABLE)))
|
|
return OLE_ERROR_MEMORY;
|
|
}
|
|
else {
|
|
// change the ownership to yourself
|
|
|
|
HANDLE htmp;
|
|
|
|
if (!(htmp = GlobalReAlloc (hNewDIB, 0L, GMEM_MODIFY|GMEM_SHARE))) {
|
|
htmp = DuplicateGlobal (hNewDIB, GMEM_MOVEABLE);
|
|
GlobalFree (hNewDIB);
|
|
if (!htmp)
|
|
return OLE_ERROR_MEMORY;
|
|
}
|
|
|
|
hNewDIB = htmp;
|
|
}
|
|
|
|
if (!(lpBi = (LPBITMAPINFOHEADER) GlobalLock (hNewDIB))) {
|
|
GlobalFree (hNewDIB);
|
|
return OLE_ERROR_MEMORY;
|
|
}
|
|
|
|
dwSize = GlobalSize (hNewDIB);
|
|
if (lpobj->hDIB)
|
|
GlobalFree (lpobj->hDIB);
|
|
DibUpdateStruct (lpobj, lpclient, hNewDIB, lpBi, dwSize);
|
|
return OLE_OK;
|
|
}
|
|
|
|
|
|
void INTERNAL DibUpdateStruct (lpobj, lpclient, hDIB, lpBi, dwBytes)
|
|
LPOBJECT_DIB lpobj;
|
|
LPOLECLIENT lpclient;
|
|
HANDLE hDIB;
|
|
LPBITMAPINFOHEADER lpBi;
|
|
DWORD dwBytes;
|
|
{
|
|
POINT point;
|
|
|
|
lpobj->head.lpclient = lpclient;
|
|
lpobj->sizeBytes = dwBytes;
|
|
|
|
#ifdef OLD
|
|
lpobj->xSize = point.x = (int) lpBi->biWidth;
|
|
lpobj->ySize = point.y = (int) lpBi->biHeight;
|
|
ConvertToHimetric (&point);
|
|
#else
|
|
DibGetExtents ((LPSTR) lpBi, &point);
|
|
#endif
|
|
|
|
lpobj->head.cx = (LONG) point.x;
|
|
lpobj->head.cy = (LONG) point.y;
|
|
lpobj->hDIB = hDIB;
|
|
}
|
|
|
|
|
|
|
|
OLESTATUS FARINTERNAL DibLoadFromStream (lpstream, lpclient, lhclientdoc, lpobjname, lplpoleobject, objType)
|
|
LPOLESTREAM lpstream;
|
|
LPOLECLIENT lpclient;
|
|
LHCLIENTDOC lhclientdoc;
|
|
LPSTR lpobjname;
|
|
LPOLEOBJECT FAR * lplpoleobject;
|
|
LONG objType;
|
|
{
|
|
LPOBJECT_DIB lpobj = NULL;
|
|
|
|
*lplpoleobject = NULL;
|
|
|
|
if (!(lpobj = DibCreateBlank (lhclientdoc, lpobjname, objType)))
|
|
return OLE_ERROR_MEMORY;
|
|
|
|
lpobj->head.lpclient = lpclient;
|
|
if (GetBytes (lpstream, (LPSTR) &lpobj->head.cx, sizeof(LONG)))
|
|
goto errLoad;
|
|
|
|
if (GetBytes (lpstream, (LPSTR) &lpobj->head.cy, sizeof(LONG)))
|
|
goto errLoad;
|
|
|
|
if (GetBytes (lpstream, (LPSTR) &lpobj->sizeBytes, sizeof(LONG)))
|
|
goto errLoad;
|
|
|
|
if (DibStreamRead (lpstream, lpobj)) {
|
|
*lplpoleobject = (LPOLEOBJECT) lpobj;
|
|
return OLE_OK;
|
|
}
|
|
|
|
errLoad:
|
|
OleDelete ((LPOLEOBJECT) lpobj);
|
|
return OLE_ERROR_STREAM;
|
|
}
|
|
|
|
|
|
|
|
LPOBJECT_DIB FARINTERNAL DibCreateBlank (lhclientdoc, lpobjname, objType)
|
|
LHCLIENTDOC lhclientdoc;
|
|
LPSTR lpobjname;
|
|
LONG objType;
|
|
{
|
|
HOBJECT hobj;
|
|
LPOBJECT_DIB lpobj;
|
|
|
|
if((hobj = GlobalAlloc (GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof (OBJECT_DIB)))
|
|
== NULL)
|
|
return NULL;
|
|
|
|
if (!(lpobj = (LPOBJECT_DIB) GlobalLock (hobj))){
|
|
GlobalFree (hobj);
|
|
return NULL;
|
|
}
|
|
|
|
// The structure is ZERO initialized at allocation time. So only the
|
|
// fields that need to be filled with values other than ZEROS are
|
|
// initialized below
|
|
|
|
lpobj->head.objId[0] = 'L';
|
|
lpobj->head.objId[1] = 'E';
|
|
lpobj->head.mm = MM_TEXT;
|
|
lpobj->head.ctype = objType;
|
|
lpobj->head.lpvtbl = (LPOLEOBJECTVTBL)&vtblDIB;
|
|
lpobj->head.iTable = INVALID_INDEX;
|
|
lpobj->head.hobj = hobj;
|
|
|
|
if (objType == CT_STATIC)
|
|
DocAddObject ((LPCLIENTDOC) lhclientdoc,
|
|
(LPOLEOBJECT) lpobj, lpobjname);
|
|
return lpobj;
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL INTERNAL DibStreamRead (lpstream, lpobj)
|
|
LPOLESTREAM lpstream;
|
|
LPOBJECT_DIB lpobj;
|
|
{
|
|
HANDLE hDIBbuf;
|
|
LPSTR lpDIBbuf;
|
|
BOOL retVal = FALSE;
|
|
BITMAPINFOHEADER bi;
|
|
|
|
if (GetBytes (lpstream, (LPSTR) &bi, sizeof(bi)))
|
|
return FALSE;
|
|
|
|
if (hDIBbuf = GlobalAlloc (GMEM_MOVEABLE, lpobj->sizeBytes)) {
|
|
if (lpDIBbuf = (LPSTR)GlobalLock (hDIBbuf)){
|
|
*((LPBITMAPINFOHEADER) lpDIBbuf) = bi;
|
|
if (!GetBytes (lpstream, lpDIBbuf+sizeof(bi),
|
|
(lpobj->sizeBytes - sizeof(bi)))) {
|
|
|
|
lpobj->hDIB = hDIBbuf;
|
|
#ifdef OLD
|
|
//!!! this info should be part of the stream
|
|
if (!lpobj->head.cx) {
|
|
DibGetExtents ((LPSTR) lpDIBbuf, &point);
|
|
lpobj->head.cx = (LONG) point.x;
|
|
lpobj->head.cy = (LONG) point.y;
|
|
}
|
|
#endif
|
|
retVal = TRUE;
|
|
}
|
|
GlobalUnlock(hDIBbuf);
|
|
}
|
|
//* Hang on to the memory allocated for the DIB
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
|
|
OLESTATUS FARINTERNAL DibPaste (lpclient, lhclientdoc, lpobjname, lplpoleobject, objType)
|
|
LPOLECLIENT lpclient;
|
|
LHCLIENTDOC lhclientdoc;
|
|
LPSTR lpobjname;
|
|
LPOLEOBJECT FAR * lplpoleobject;
|
|
LONG objType;
|
|
{
|
|
HANDLE hDIB;
|
|
|
|
if ((hDIB = GetClipboardData (CF_DIB)) == NULL)
|
|
return OLE_ERROR_MEMORY;
|
|
|
|
*lplpoleobject = (LPOLEOBJECT) DibCreateObject (hDIB, lpclient, FALSE,
|
|
lhclientdoc, lpobjname, objType);
|
|
|
|
return OLE_OK;
|
|
|
|
}
|
|
|
|
|
|
void FARINTERNAL DibGetExtents (lpData, lpPoint)
|
|
LPSTR lpData;
|
|
LPPOINT lpPoint;
|
|
{
|
|
#define HIMET_PER_METER 100000L // number of HIMETRIC units / meter
|
|
|
|
LPBITMAPINFOHEADER lpbmi;
|
|
|
|
lpbmi = (LPBITMAPINFOHEADER)lpData;
|
|
|
|
if (!(lpbmi->biXPelsPerMeter && lpbmi->biYPelsPerMeter)) {
|
|
HDC hdc;
|
|
|
|
hdc = GetDC (NULL);
|
|
lpbmi->biXPelsPerMeter = MulDiv (GetDeviceCaps (hdc, LOGPIXELSX),
|
|
10000, 254);
|
|
lpbmi->biYPelsPerMeter = MulDiv (GetDeviceCaps (hdc, LOGPIXELSY),
|
|
10000, 254);
|
|
|
|
ReleaseDC (NULL, hdc);
|
|
}
|
|
|
|
lpPoint->x = (int) (lpbmi->biWidth * HIMET_PER_METER
|
|
/ lpbmi->biXPelsPerMeter);
|
|
lpPoint->y = -(int) (lpbmi->biHeight * HIMET_PER_METER
|
|
/ lpbmi->biYPelsPerMeter);
|
|
}
|
|
|