Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1719 lines
48 KiB

/*
* PBSERVER.C - Code to make PaintBrush an OLE server application
*
* Adapted from RaoR's "Shapes" sample server
*/
#include <windows.h>
#include "port1632.h"
#include "pbrush.h"
#include "pbserver.h"
#include <shellapi.h>
#ifdef WIN32
#define huge
#endif
int iExitWithSaving = IDNO;
/* Clipboard formats */
WORD vcfLink = 0;
WORD vcfOwnerLink = 0;
WORD vcfNative = 0;
/* After the user chooses not to update an object while closing the server
* this flag prevents data being sent before the server closes down */
BOOL fSendData = TRUE; /* return NULL data from ItemGetData()? */
/* OLE document/object/server virtual tables */
OLESERVERDOCVTBL vdocvtbl;
OLEOBJECTVTBL vitemvtbl;
OLESERVERVTBL vsrvrvtbl;
/* Are we running a Link or the non-OLE case? */
BOOL vfIsLink = TRUE;
/* Since Paint is not an MDI application, only one document can be
* edited per instance. The items are just RECTs over (windows onto)
* the document, which may overlap.
*/
HANDLE hServer = NULL;
PPBSRVR vpsrvr = NULL;
PPBDOC vpdoc = NULL;
PITEM vpitem[CMAXITEMS];
int cItems = 0;
int nCmdShowSaved = 0;
/* What part of the image has been modified? */
RECT vrcModified;
/* Swiped from SaveBitmapFile() */
#define DIBID 0x4D42
#define CBMENUITEMMAX 80
extern HBITMAP fileBitmap;
extern int imageWid, imageHgt, imagePlanes, imagePixels;
extern HWND pbrushWnd[];
extern TCHAR pathName[];
extern TCHAR fileName[];
extern TCHAR noFile[];
extern WORD wFileType;
extern BOOL imageFlag;
extern TCHAR *namePtr;
extern HDC fileDC;
extern TCHAR filePath[];
extern HPALETTE hPalette;
extern BOOL bZoomedOut;
extern HWND zoomOutWnd;
/* Function prototypes */
void PUBLIC NewImage(int); /* MenuCmd.C */
static void FixMenus(void); /* Update, Save Copy As..., Exit and Return */
static void GetNum(LPTSTR FAR *lplpstrBuf, LPINT lpint);
static void MakeObjectVisible(
LPRECT lpItemRect);
int PelsPerLogMeter(HDC hDC,BOOL bHoriz);
int PelsToLogHimetric(HDC hDC,BOOL bHoriz, int pels);
/* InitVTbls() is in srvrinit.c */
/* MACROS: */
/* Fix the menus for the embedded instance */
#define ChangeMenuItem(id, idnew, sz) \
ModifyMenu(hMenu, id, MF_BYCOMMAND | MF_STRING, idnew, sz)
#ifndef OLE_20
# define FreeOleString(s) \
if((s) == NULL) { /* do nothing */ ; } else LocalFree(s)
BOOL SetOleString(LPTSTR *ppstr, POLESTR postr) {
int cb;
DB_OUT("In SetOleString ");
*ppstr = NULL;
DB_OUT2( postr == NULL, "SOS(NULL) ", "SOS(OK) ");
if (postr == NULL)
return TRUE;
DB_OUT( "SOS(call MBTWC 1) " );
cb = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, postr, -1, NULL, 0);
DB_OUT( "SOS(call LA) " );
*ppstr = LocalAlloc(LPTR, cb * sizeof(WCHAR));
if (*ppstr != NULL) {
DB_OUT( "SOS(call MBTWC 2) " );
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, postr, -1, *ppstr, cb);
}
DB_OUT( "Out SetOleString\n" );
return *ppstr != NULL;
}
#else
# define FreeOleString(s)
# define SetOleString(s,o) (*s) = o
#endif
void FreeVTbls(void) {
/* Server virtual table */
FreeProcInstance((FARPROC)vsrvrvtbl.Open);
FreeProcInstance((FARPROC)vsrvrvtbl.Create);
FreeProcInstance((FARPROC)vsrvrvtbl.CreateFromTemplate);
FreeProcInstance((FARPROC)vsrvrvtbl.Edit);
FreeProcInstance((FARPROC)vsrvrvtbl.Exit);
FreeProcInstance((FARPROC)vsrvrvtbl.Release);
/* Document virtual table */
FreeProcInstance((FARPROC)vdocvtbl.Save);
FreeProcInstance((FARPROC)vdocvtbl.Close);
FreeProcInstance((FARPROC)vdocvtbl.GetObject);
FreeProcInstance((FARPROC)vdocvtbl.Release);
FreeProcInstance((FARPROC)vdocvtbl.SetHostNames);
FreeProcInstance((FARPROC)vdocvtbl.SetDocDimensions);
FreeProcInstance((FARPROC)vdocvtbl.SetColorScheme);
/* Item virtual table */
FreeProcInstance((FARPROC)vitemvtbl.QueryProtocol);
FreeProcInstance((FARPROC)vitemvtbl.GetData);
FreeProcInstance((FARPROC)vitemvtbl.SetData);
FreeProcInstance((FARPROC)vitemvtbl.Release);
FreeProcInstance((FARPROC)vitemvtbl.Show);
FreeProcInstance((FARPROC)vitemvtbl.SetBounds);
FreeProcInstance((FARPROC)vitemvtbl.SetTargetDevice);
FreeProcInstance((FARPROC)vitemvtbl.EnumFormats);
FreeProcInstance((FARPROC)vitemvtbl.SetColorScheme);
FreeProcInstance((FARPROC)vitemvtbl.DoVerb);
}
/************************ App Server Functions ************************/
/* InitServer() is in srvrinit.c */
/* If fServerRevoked is TRUE then Server has been revoked,so
* we can free server structures and close Pbrush. */
BOOL fServerRevoked = FALSE;
void DeleteServer(PPBSRVR psrvr) {
OLESTATUS olestat;
if (!fServerRevoked) { /* if server is not revoked yet */
fServerRevoked = TRUE;
olestat = OleRevokeServer(psrvr->lhsrvr);
if (!(olestat == OLE_OK || olestat == OLE_WAIT_FOR_RELEASE)) {
#ifdef DEBUG
PbrushOkError(W_FAILED_TO_REVOKE_SERVER, MB_ICONHAND);
#endif
fServerRevoked = FALSE;
}
}
}
/************************* SERVER VTBL FUNCTIONS **************************/
/* Open a server document.
* Load the given file and register a server DOC.
*/
OLESTATUS FAR PASCAL SrvrOpen(LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc,
POLESTR lpOLEdocname, LPOLESERVERDOC FAR *lplpoledoc) {
LPTSTR lpDocName;
DB_OUT("In SrvrOpen ");
if (!SetOleString(&lpDocName, lpOLEdocname)) {
DB_OUT("ERR SrvrOpen\n");
return OLE_ERROR_GENERIC;
}
if (!(*lplpoledoc =
(LPOLESERVERDOC)CreateDocFromFile((PPBSRVR)lpolesrvr,
lpDocName, lhdoc, lpDocName))) {
FreeOleString(lpDocName);
DB_OUT("ERR SrvrOpen\n");
return OLE_ERROR_BLANK;
}
SetTitle(*fileName ? fileName : noFile);
FreeOleString(lpDocName);
DB_OUT("Out SrvrOpen\n");
return OLE_OK;
}
/* Create a new server doc. */
OLESTATUS FAR PASCAL SrvrCreate(LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc,
POLESTR lpclassname, POLESTR lpdocname, LPOLESERVERDOC FAR *lplpoledoc) {
LPTSTR lpDocName;
DB_OUT("In SrvrCreate ");
if (!SetOleString(&lpDocName, lpdocname)) {
DB_OUT("ERR SrvrCreate\n");
return OLE_ERROR_GENERIC;
}
/* Initialize the new image */
SendMessage(pbrushWnd[PARENTid], WM_COMMAND, FILEnew, 0L);
if (!(*lplpoledoc =
(LPOLESERVERDOC)CreateNewDoc((PPBSRVR)lpolesrvr, lhdoc, lpDocName))){
FreeOleString(lpDocName);
DB_OUT("ERR SrvrCreate\n");
return OLE_ERROR_MEMORY;
}
FixMenus(); /* Change Save to Update */
imageFlag = TRUE;
FreeOleString(lpDocName);
DB_OUT("Out SrvrCreate\n");
return OLE_OK;
}
/* Create a server doc from template. Similar to SrvrOpen except the
* title is different */
OLESTATUS FAR PASCAL SrvrCreateFromTemplate(LPOLESERVER lpolesrvr,
LHSERVERDOC lhdoc, POLESTR lpclassname, POLESTR lpOLEdocname,
POLESTR lpOLEtemplatename, LPOLESERVERDOC FAR *lplpoledoc) {
PPBDOC pdoc;
LPTSTR lptemplatename;
LPTSTR lpdocname;
OLESTATUS ret;
DB_OUT("In SrvrCreateFromTemplate ");
if (!SetOleString(&lptemplatename, lpOLEtemplatename)) {
DB_OUT("ERR SrvrCreateFromTemplate\n");
return OLE_ERROR_GENERIC;
}
if (!SetOleString(&lpdocname, lpOLEdocname)) {
FreeOleString(lptemplatename);
DB_OUT("ERR SrvrCreateFromTemplate\n");
return OLE_ERROR_GENERIC;
}
if (!(pdoc = (PPBDOC)CreateDocFromFile((PPBSRVR)lpolesrvr, lptemplatename, lhdoc, lpdocname)))
ret = OLE_ERROR_BLANK;
else {
/* Open the template and give it the correct name */
lstrcpy(noFile, lpdocname);
SetTitle(noFile);
*lplpoledoc = (LPOLESERVERDOC)pdoc;
FixMenus(); /* Change Save to Update */
imageFlag = TRUE;
ret = OLE_OK;
}
FreeOleString(lpdocname);
FreeOleString(lptemplatename);
DB_OUT("Out SrvrCreateFromTemplate\n");
return ret;
}
/* Create a new server doc. It will be initialized later on by a call
* to ItemSetData() */
OLESTATUS FAR PASCAL SrvrEdit(LPOLESERVER lpolesrvr, LHSERVERDOC lhdoc,
POLESTR lpOLEclassname, POLESTR lpOLEdocname, LPOLESERVERDOC FAR *lplpoledoc) {
LPTSTR lpdocname;
DB_OUT("In SrvrEdit ");
if (!SetOleString(&lpdocname, lpOLEdocname)) {
DB_OUT("ERR SrvrEdit\n");
return OLE_ERROR_GENERIC;
}
DB_OUT("SE1 ");
if (!(*lplpoledoc =
(LPOLESERVERDOC)CreateNewDoc((PPBSRVR)lpolesrvr, lhdoc, lpdocname))) {
DB_OUT("SE2 ");
FreeOleString(lpdocname);
DB_OUT("ERR SrvrEdit\n");
return OLE_ERROR_MEMORY;
}
DB_OUT("SE3 ");
FixMenus(); /* Change Save to Update */
DB_OUT("SE4 ");
FreeOleString(lpdocname);
DB_OUT("Out SrvrEdit\n");
return OLE_OK;
}
/* Server should exit */
OLESTATUS FAR PASCAL SrvrExit(LPOLESERVER lpolesrvr) {
PPBSRVR psrvr = (PPBSRVR) lpolesrvr;
DB_OUT("In SrvrExit ");
DeleteServer(psrvr);
DB_OUT("Out SrvrExit\n");
return OLE_OK;
}
/* Server should exit only if it is invisible OR
* if it was launched as a server and does not have any open doc */
OLESTATUS FAR PASCAL SrvrRelease(LPOLESERVER lpolesrvr) {
PPBSRVR psrvr = (PPBSRVR)lpolesrvr;
DB_OUT( "In SrvrRelease ");
/* If Pbrush is still invisible then it is OK to exit, OR
* If Pbrush was launched as a server and there are no docs, then exit. */
if (fInvisible || (fServer && !vpdoc))
DeleteServer(psrvr);
if (fServerRevoked && hServer) {
/* Release the server virtual table and info */
GlobalUnlock(hServer);
GlobalFree(hServer);
hServer = NULL;
/* Destroy the window only when we're all through */
if (pbrushWnd[PARENTid])
DestroyWindow(pbrushWnd[PARENTid]);
}
DB_OUT( "Out SrvrRelease\n");
return OLE_OK;
}
/********************* DOCUMENT FUNCTIONS ********************/
/* InitDoc() is in srvrinit.c */
void DeleteDoc(PPBDOC pdoc) {
OLESTATUS olestat;
if (pdoc) {
if (iExitWithSaving != IDNO)
SendDocChangeMsg(pdoc, OLE_CLOSED);
olestat = OleRevokeServerDoc(pdoc->lhdoc);
#ifdef DEBUG
if (olestat != OLE_OK && olestat != OLE_WAIT_FOR_RELEASE)
PbrushOkError(W_FAILED_TO_REVOKE_DOCUMENT, MB_ICONHAND);
#endif
vpdoc = NULL;
}
}
void ChangeDocName(PPBDOC FAR *ppdoc, LPTSTR lpname)
{
#ifndef OLE_20
CHAR szAnsi[FILENAMElen + PATHlen];
#endif
if (*ppdoc)
{
if ((*ppdoc)->aName)
GlobalDeleteAtom((*ppdoc)->aName);
(*ppdoc)->aName = GlobalAddAtom(lpname);
#ifndef OLE_20
WideCharToMultiByte (CP_ACP, 0, lpname, -1, szAnsi, FILENAMElen + PATHlen, NULL, NULL);
OleRenameServerDoc((*ppdoc)->lhdoc, szAnsi);
#else
OleRenameServerDoc((*ppdoc)->lhdoc, lpname);
#endif
if (cItems)
return;
/* This won't be necessary when Rename works */
DeleteDoc(*ppdoc);
}
*ppdoc = InitDoc(vpsrvr, 0, lpname);
}
/********************** Document VTable Functions *********************/
OLESTATUS FAR PASCAL DocSave(LPOLESERVERDOC lpoledoc) {
/*
* The document will only have one client
* area, so there is only one item to save.
*/
DB_OUT("In DocSave ");
/* Call paintbrush save document routine */
SendMessage(pbrushWnd[PARENTid], WM_COMMAND, FILEsave, 0L);
DB_OUT("Out DocSave\n");
return OLE_OK;
}
/* If the OLE library is requesting the doc delete, and not the user,
* the client app is going away and we should kill ourselves.
*/
OLESTATUS FAR PASCAL DocClose(LPOLESERVERDOC lpoledoc) {
PPBDOC pdoc = (PPBDOC)lpoledoc;
DB_OUT("In DocClose ");
DeleteDoc(pdoc);
DeleteServer(vpsrvr);
DB_OUT("Out DocClose\n");
return OLE_OK;
}
OLESTATUS FAR PASCAL DocRelease(LPOLESERVERDOC lpoledoc) {
PPBDOC pdoc = (PPBDOC)lpoledoc;
HANDLE hdoc;
DB_OUT("In DocRelease ");
if (pdoc->aName)
GlobalDeleteAtom(pdoc->aName);
GlobalUnlock(hdoc = pdoc->hdoc);
GlobalFree(hdoc);
DB_OUT("Out DocRelease\n");
return OLE_OK;
}
/* Retrieve an item/object in a document.
* An item is a rectangle in a picture.
* For linked objects, it could be part of an image.
*/
OLESTATUS FAR PASCAL DocGetObject(LPOLESERVERDOC lpoledoc, POLESTR pitemname,
LPOLEOBJECT FAR *lplpoleobject, LPOLECLIENT lpoleclient) {
PITEM pitem;
RECT rcImage;
LPTSTR pItemName;
OLESTATUS oleStat = OLE_ERROR_GENERIC;
DB_OUT("In DocGetObject ");
if (!SetOleString(&pItemName, pitemname))
goto errRtn;
/*
* Always create a new item in this case, it's much easier than
* worrying about the sub-rectangle bitmap. AddItem will remove
* duplicates, and remove the item when its reference count is 0.
*/
*lplpoleobject = NULL;
if (!(pitem = CreateNewItem((PPBDOC)lpoledoc)))
goto errRtn;
pitem->lpoleclient = lpoleclient;
/* The first time around, imageWid and imageHgt will only have
* values if we are a linked object.
*/
SetRect(&rcImage, 0, 0, imageWid, imageHgt);
if (*pItemName) {
RECT rcIntersect;
ScanRect(pItemName, &(pitem->rc));
/* Perform item name validation checks in the linked case */
if (vfIsLink
&& (!IntersectRect(&rcIntersect, &pitem->rc, &rcImage)
|| !EqualRect(&rcIntersect, &pitem->rc)))
goto errRtn;
pitem->aName = AddAtom(pItemName);
} else {
/* NULL item: No rectangle to scan, use the image size */
pitem->rc = rcImage;
pitem->aName = 0;
}
*lplpoleobject = (LPOLEOBJECT)AddItem(pitem);
oleStat = OLE_OK;
errRtn:
if (oleStat != OLE_OK) {
PbrushOkError(E_INVALID_ITEM_NAME, MB_ICONHAND);
if (pitem) {
HANDLE hitem;
GlobalUnlock(hitem = pitem->hitem);
GlobalFree(hitem);
}
}
FreeOleString(pItemName);
DB_OUT("Out DocGetObject\n");
return oleStat;
}
TCHAR szClientName[MAXCLIENTNAME];
/*
* Called for Embedded objects only.
* Set the title bar to "Paintbrush - Paintbrush Picture in <lpdocName>".
* Also change the File.Exit to "Exit & Return to <lpdocName>"
*/
OLESTATUS FAR PASCAL DocSetHostNames(LPOLESERVERDOC lpoledoc,
POLESTR lpOLEclientName, POLESTR lpOLEdocName)
{
DWORD dwSize = KEYNAMESIZE;
TCHAR szLoader[OBJSTRINGSMAX];
TCHAR szBuffer[KEYNAMESIZE + 100];
TCHAR szClass[KEYNAMESIZE];
TCHAR szMenuStrFormat[CBMENUITEMMAX];
HMENU hMenu;
TCHAR lpFile[MAX_PATH];
LPTSTR lpdocName, lpclientName;
DB_OUT("In DocSetHostNames ");
if (!SetOleString(&lpdocName, lpOLEdocName)) {
DB_OUT("ERR DocSetHostNames\n");
return OLE_ERROR_GENERIC;
}
if (!SetOleString(&lpclientName, lpOLEclientName)) {
FreeOleString(lpdocName);
DB_OUT("ERR DocSetHostNames\n");
return OLE_ERROR_GENERIC;
}
// IDSPicture = "Paintbrush Picture"
lstrcpy(szClientName, lpclientName);
if (RegQueryValue(HKEY_CLASSES_ROOT, TEXT("PBrush"), szClass, (PLONG)&dwSize))
{
LoadString(hInst, IDSpicture, szClass, CharSizeOf(szClass));
}
lstrcpy (lpFile, PFileInPath(lpdocName));
if (lpFile[0] == (TCHAR) 0)
LoadString(hInst, IDSuntitled, lpFile, CharSizeOf(lpFile));
LoadString (hInst, IDSxiny, szLoader, CharSizeOf(szLoader));
#ifdef JAPAN // added by Hiraisi (BUG#3989/WIN31)
wsprintf(szBuffer, szLoader, lpFile);
#else
wsprintf (szBuffer, szLoader, szClass, lpFile);
#endif
lstrcpy (fileName, lpFile);
SetTitle (szBuffer);
LoadString (hInst, IDS_EXITANDRETURN, szMenuStrFormat, CharSizeOf(szMenuStrFormat));
wsprintf (szBuffer, szMenuStrFormat, lpFile);
hMenu = GetMenu (pbrushWnd[PARENTid]);
ModifyMenu (hMenu, FILEexit, MF_BYCOMMAND | MF_STRING, FILEexit, szBuffer);
FreeOleString(lpdocName);
FreeOleString(lpclientName);
DB_OUT("Out DocSetHostNames\n");
return OLE_OK;
}
OLESTATUS FAR PASCAL DocSetDocDimensions(LPOLESERVERDOC lpoledoc, LPRECT lprc) {
/* Links should never call this function, but we will never
* succeed in resizing the BITMAP (no plans to re-BitBlt()).
*/
#ifdef DEBUG
if (vfIsLink)
PbrushOkError(E_SET_DIMENSIONS_UNSUPPORTED, MB_ICONEXCLAMATION);
else
PbrushOkError(W_SET_DIMENSIONS_UNSUPPORTED, MB_ICONINFORMATION);
#endif
return OLE_OK;
}
OLESTATUS FAR PASCAL DocSetColorScheme(LPOLESERVERDOC lpoledoc, LPLOGPALETTE lppal) {
HPALETTE hNewPal;
DB_OUT("In DocSetColorScheme ");
if (!(hNewPal = CreatePalette(lppal))) {
DB_OUT("ERR DocSetColorScheme\n");
return OLE_ERROR_GENERIC;
}
if (hNewPal != hPalette) {
SelectPalette(hdcWork, hNewPal, 0);
RealizePalette(hdcWork);
SelectPalette(hdcImage, hNewPal, 0);
RealizePalette(hdcImage);
#ifdef WANT_RIPS
DeleteObject(hPalette);
#endif
hPalette = hNewPal;
}
DB_OUT("Out DocSetColorScheme\n");
return OLE_OK;
}
/**************************** ITEM SUBROUTINES ***************************/
void FAR CutCopyObjectFormats(HDC hDC, HBITMAP hBitmap, RECT rc, UINT msg) {
/* This function is called when the clipboard is already opened */
HANDLE hdata = NULL;
RECT rc2;
/* Set the Clipboard */
/* Native data... (in our case, the item rectangle sub-BITMAP) */
/* Return a handle to native data (DIB file format) */
if (hdata = GetNative(hDC, hBitmap, rc))
SetClipboardData(vcfNative, hdata);
/* Link data... (PBrush\0<Doc name>\0<Item name>\0\0) */
/* Don't copy a link if the doc has no name, or if it's a CUT operation */
if (vfIsLink && (*fileName) && msg != WM_CUT && theTool != SCISSORStool
&& (hdata = GetLink(rc)))
SetClipboardData(vcfLink, hdata);
SetRect(&rc2, 0, 0, rc.right - rc.left, rc.bottom - rc.top);
/* Reconstruct this, for the time being */
if (hdata = GetLink(rc2))
SetClipboardData(vcfOwnerLink, hdata);
/* Metafile data */
/* Skip metafile copy if we are in 3.0 compatibility mode */
if (!fOmitPictureFormat && (hdata = GetMF(hDC, hBitmap, rc)))
SetClipboardData(CF_METAFILEPICT, hdata);
}
PITEM CreateNewItem(PPBDOC pdoc) {
HANDLE hitem = NULL;
PITEM pitem = NULL;
/* Now create the item */
hitem = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(ITEM));
if (!hitem || (!(pitem = (PITEM) GlobalLock(hitem))))
goto errRtn;
pitem->hitem = hitem;
pitem->oleobject.lpvtbl = &vitemvtbl;
/* pitem->rc will be filled out by the caller */
return pitem;
errRtn:
if (pitem)
GlobalUnlock(hitem);
if (hitem)
GlobalFree(hitem);
return NULL;
}
BOOL SendDocChangeMsg(PPBDOC pdoc, WORD options) {
BOOL fSuccess = FALSE;
int i;
#ifdef LATER
RECT rc;
#endif
for (i = 0; i < cItems; i++) {
#ifdef LATER
/* If item has been updated, ... */
if (IntersectRect(&rc, &vrcModified, &vpitem[i].rc))
#endif
fSuccess = SendItemChangeMsg(vpitem[i], options) || fSuccess;
}
return fSuccess;
}
BOOL SendItemChangeMsg(PITEM pitem, WORD options) {
if (pitem->lpoleclient) {
(*pitem->lpoleclient->lpvtbl->CallBack)
(pitem->lpoleclient, options, (LPOLEOBJECT)pitem);
return TRUE;
}
return FALSE;
}
/********************* Item VTable Subroutines **************************/
OLESTATUS FAR PASCAL ItemDelete(LPOLEOBJECT lpoleobject) {
DB_OUT("In ItemDelete ");
DeleteItem((PITEM)lpoleobject);
DB_OUT("Out ItemDelete\n");
return OLE_OK; /* Add error checking later */
}
OLESTATUS FAR PASCAL ItemGetData(LPOLEOBJECT lpoleobject,
OLECLIPFORMAT cfFormat, LPHANDLE lphandle) {
HCURSOR hcurOld;
PITEM pitem = (PITEM)lpoleobject;
DB_OUT("In ItemGetData ");
/* Suppress data updates? */
if (!fSendData) {
*lphandle = NULL;
return OLE_OK;
}
hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
if (cfFormat == vcfNative) {
*lphandle = GetNative(NULL, NULL, pitem->rc);
} else if (cfFormat == vcfLink) {
*lphandle = GetLink(pitem->rc);
} else if (cfFormat == CF_METAFILEPICT) {
*lphandle = GetMF(NULL, NULL, pitem->rc);
} else if ((cfFormat == CF_BITMAP) || (cfFormat == CF_DIB)) {
*lphandle = GetBitmap(pitem);
} else if (cfFormat == vcfOwnerLink) {
RECT rc2;
SetRect(&rc2, 0, 0, pitem->rc.right - pitem->rc.left,
pitem->rc.bottom - pitem->rc.top);
*lphandle = GetLink(rc2);
}
SetCursor(hcurOld);
DB_OUT("Out ItemGetData\n");
return (*lphandle) ? OLE_OK : OLE_ERROR_MEMORY;
}
OLESTATUS FAR PASCAL ItemSetData(LPOLEOBJECT lpoleobject,
OLECLIPFORMAT cfFormat, HANDLE hdata) {
/*
* Read in the embedded object data in Native format.
* (or Link format). Presumably this will not be called
* unless we are editing the correct document.
*/
BOOL fError = FALSE;
PITEM pitem = (PITEM)lpoleobject;
HCURSOR hcurOld;
DB_OUT("In ItemSetData ");
hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
if (cfFormat == vcfNative)
fError = PutNative(pitem, pbrushWnd[PAINTid], hdata);
/* We should also be able to accept an HBITMAP here */
SetCursor(hcurOld);
GlobalFree(hdata);
DB_OUT("Out ItemSetData\n");
return fError ? OLE_ERROR_GENERIC : OLE_OK;
}
OLESTATUS FAR PASCAL ItemShow(LPOLEOBJECT lpoleobject, BOOL fActivate) {
PITEM pitem = (PITEM)lpoleobject;
RECT rcTemp;
DB_OUT("In ItemShow ");
if (fActivate) {
fInvisible = FALSE;
/* Show the item. This routine is called when the user
* double clicks in the client application, and the PBrush
* server is already active. If iconic, restore the window;
* then give it the focus.
*/
if (IsIconic(pbrushWnd[PARENTid]))
SendMessage(pbrushWnd[PARENTid], WM_SYSCOMMAND, SC_RESTORE, 0L);
SetForegroundWindow(pbrushWnd[PARENTid]);
BringWindowToTop(pbrushWnd[PARENTid]);
/* If it's a link, be sure to show the item */
if (vfIsLink) {
// int itemHeight, itemWidth;
if (bZoomedOut)
SendMessage(zoomOutWnd, WM_KEYDOWN, VK_ESCAPE, 0L);
else if (inMagnify)
SendMessage(pbrushWnd[PARENTid], WM_COMMAND,
GET_WM_COMMAND_MPS(MISCzoomOut, NULL, 0));
#if 0
/* if item is larger than the paint Window, MAXIMIZE to show the
* entire image */
itemWidth = pitem->rc.right - pitem->rc.left;
itemHeight = pitem->rc.bottom - pitem->rc.top;
if (itemWidth >= (imageView.right - imageView.left) ||
itemHeight >= (imageView.bottom - imageView.top))
SendMessage(pbrushWnd[PARENTid], WM_SYSCOMMAND, SC_MAXIMIZE, 0L);
#endif
/* check if the image has to be scrolled into view */
IntersectRect(&rcTemp, &(pitem->rc), &imageView);
if (!EqualRect(&rcTemp, &(pitem->rc)))
MakeObjectVisible((LPRECT)&(pitem->rc));
/* Set the tool to "rectangle" selection */
SendMessage(pbrushWnd[TOOLid], WM_SELECTTOOL, PICKtool, 0L);
/* Now, draw the selection rectangle */
InvalidateRect(pbrushWnd[PARENTid], NULL, FALSE);
UpdateWindow(pbrushWnd[PARENTid]);
DOUTR(L"ItemShow: sending WM_TERMINATE");
SendMessage(pbrushWnd[PAINTid], WM_TERMINATE, 0, 0L);
pickRect = pitem->rc;
--pickRect.bottom;
--pickRect.right;
OffsetRect(&pickRect, -imageView.left, -imageView.top);
/* If more than one instance of pbrush is launched while editing
* multiple links, focus changes back and forth and we don't want
* the image with outline to be retrieved.
* Use TerminateKill to avoid saving this intermediate form of the image.
*/
TerminateKill = FALSE;
SendMessage(pbrushWnd[PAINTid], WM_OUTLINE, 0, 0L);
TerminateKill = TRUE;
} else /* Force a full frame redraw */
InvalidateRect(pbrushWnd[PARENTid], NULL, FALSE);
}
DB_OUT("Out ItemShow\n");
return OLE_OK;
}
static void MakeObjectVisible(
LPRECT lpItemRect)
{
int xPos;
int yPos;
/* Fix the x coordinate */
if (lpItemRect->left < imageView.left)
xPos = lpItemRect->left;
else if (lpItemRect->right > imageView.right)
xPos = imageView.left + (lpItemRect->right - imageView.right);
else
xPos = imageView.left; /* unchanged */
/* Fix the y coordinate */
if (lpItemRect->top < imageView.top)
yPos = lpItemRect->top;
else if (lpItemRect->bottom > imageView.bottom)
yPos = imageView.top + (lpItemRect->bottom - imageView.bottom);
else
yPos = imageView.top; /* unchanged */
/* Scroll the image */
if (xPos != imageView.left)
SendMessage(pbrushWnd[PAINTid], WM_HSCROLL,
SB_THUMBPOSITION, MAKELONG(xPos, 0));
if (yPos != imageView.top)
SendMessage(pbrushWnd[PAINTid], WM_VSCROLL,
SB_THUMBPOSITION, MAKELONG(yPos, 0));
}
OLESTATUS FAR PASCAL ItemSetBounds(LPOLEOBJECT lpoleobject, LPRECT lprc) {
/* Again, we won't allow the BITMAP dimensions to change */
#ifdef DEBUG
if (vfIsLink)
PbrushOkError(E_SET_DIMENSIONS_UNSUPPORTED, MB_ICONEXCLAMATION);
else
PbrushOkError(W_SET_DIMENSIONS_UNSUPPORTED, MB_ICONINFORMATION);
#endif
return OLE_ERROR_GENERIC;
}
OLESTATUS FAR PASCAL ItemSetTargetDevice(LPOLEOBJECT lpoleobject, HANDLE h) {
#ifdef DEBUG
PbrushOkError(W_SET_TARGET_DEVICE_UNSUPPORTED, MB_ICONINFORMATION);
#endif
if (h)
GlobalFree(h);
return OLE_ERROR_GENERIC;
}
OLECLIPFORMAT FAR PASCAL ItemEnumFormats(LPOLEOBJECT lpobject,
OLECLIPFORMAT cfFormat) {
/* This is called by the OLE libraries to get a format for
* display on the screen.
*/
DB_OUT("In ItemEnumFormats ");
if (!cfFormat) {
DB_OUT("Out1 ItemEnumFormats\n");
return CF_BITMAP;
}
if ((cfFormat == CF_BITMAP) || (cfFormat == CF_DIB)) {
DB_OUT("Out2 ItemEnumFormats\n");
return CF_METAFILEPICT;
}
if (cfFormat == CF_METAFILEPICT) {
DB_OUT("Out3 ItemEnumFormats\n");
return vcfNative;
}
return 0;
}
LPVOID FAR PASCAL ItemQueryProtocol(LPOLEOBJECT lpoleobject, POLESTR lpprotocol) {
LPVOID lpv;
DB_OUT("In ItemQueryProtocol ");
#ifndef OLE_20
lpv = (!lstrcmpiA(lpprotocol, "StdFileEditing") ? lpoleobject : NULL);
#else
lpv = (!lstrcmpi(lpprotocol, TEXT("StdFileEditing")) ? lpoleobject : NULL);
#endif
DB_OUT2(lpv == NULL, "ret NULL ", "ret obj ");
DB_OUT("Out ItemQueryProtocol\n");
return lpv;
}
OLESTATUS FAR PASCAL ItemSetColorScheme(LPOLEOBJECT lpoleobject, LPLOGPALETTE lppal) {
DB_OUT("InERROut ItemSetColorScheme\n");
return OLE_ERROR_GENERIC;
}
OLESTATUS FAR PASCAL ItemDoVerb(LPOLEOBJECT lpoleobject,
WORD wVerb, BOOL fShow, BOOL fActivate) {
OLESTATUS ols = OLE_OK;
DB_OUT("In ItemDoVerb ");
DB_OUT2(fShow, "fShow ", "No Show ");
if (fShow)
ols = (*lpoleobject->lpvtbl->Show)(lpoleobject, fActivate);
DB_OUT("Out ItemDoVerb\n" );
return ols;
}
/******************** APPLICATION SUPPLIED FUNCTIONS *********************/
PPBDOC CreateNewDoc(PPBSRVR psrvr, LHSERVERDOC lhdoc, LPTSTR lpstr) {
lstrcpy(noFile, lpstr);
SetTitle(noFile);
return (vpdoc = InitDoc(psrvr, lhdoc, lpstr));
}
PPBDOC CreateDocFromFile(PPBSRVR psrvr, LPTSTR lpstr, LHSERVERDOC lhdoc, LPTSTR lpstrDocName) {
/* Return TRUE iff document created. Call paintbrush read from file here */
LPTSTR lpTmp;
LPTSTR lpTmp2 = NULL;
/* Parse the path and the file name */
lpTmp = lpstr;
while (*lpTmp) {
if (*lpTmp == TEXT('\\'))
lpTmp2 = lpTmp;
#ifdef DBCS
lpTmp = CharNext(lpTmp);
#else
lpTmp++;
#endif
}
if (lpTmp2) { /* There was a backslash! */
*lpTmp2++ = 0;
lstrcpy(filePath, lpstr);
changeDiskDir(filePath);
lstrcpy(fileName, lpTmp2);
*(--lpTmp2) = TEXT('\\'); /* restore it */
} else {
*filePath = (TCHAR) 0;
lstrcpy(fileName, lpstr);
}
/* Read in the document */
if (LoadBitmapFile(pbrushWnd[PAINTid], fileName, NULL))
return NULL;
NewImage(0);
/* Set the initial modified bounding rect to NULL */
SetRect(&vrcModified, -1, -1, -1, -1);
/* Initialize document */
return (vpdoc = InitDoc(psrvr, lhdoc, lpstrDocName));
}
HANDLE GetNative(HDC hDC, HBITMAP hBitmap, RECT rc) {
/*
* Derived from SaveBitmapFile()
*
* The native format is the entire DIB file format
* (it is insufficient to just provide a handle).
*/
int i;
int width, height;
BOOL error = TRUE;
LPBYTE lpBits;
BYTE huge *hpBits;
HDC parentDC = NULL;
int ScanLineSize, InfoSize;
DWORD dwImgSize;
HANDLE hLink = NULL;
LPBYTE lpLink = NULL;
HCURSOR hOldCursor;
HBITMAP hOldBitmap = NULL;
HPALETTE hOldPalette = NULL;
LPBITMAPFILEHEADER lpHdr;
LPBITMAPINFO lpInfo;
LPBITMAPINFO lpbmInfo = NULL; /* deal with alignment -- FGS */
HANDLE hbmInfo=NULL;
/* Compute the rectangle to be selected */
width = (rc.right - rc.left);
height = (rc.bottom - rc.top);
hOldCursor = SetCursor(LoadCursor(NULL,IDC_WAIT));
if (!hDC) {
if (!(fileDC = CreateCompatibleDC(NULL)))
{
PbrushOkError(IDSNotEnufMem, MB_ICONHAND);
goto error1;
}
}
if (hPalette) {
hOldPalette = SelectPalette(hDC? hDC: fileDC, hPalette, 0);
RealizePalette(hDC? hDC: fileDC);
}
switch (wFileType) {
case BITMAPFILE24:
i = 24;
break;
case BITMAPFILE:
case MSPFILE:
i = 1;
break;
case BITMAPFILE4:
i = 4;
break;
case BITMAPFILE8:
i = 8;
break;
case PCXFILE:
i = imagePlanes * imagePixels;
break;
}
/* BITMAPINFOSIZE = size of header + color table. */
/* no color table for 24 bpp bitmaps. */
InfoSize = sizeof(BITMAPINFOHEADER) +
((i == 24)? 0: (sizeof(RGBQUAD) << i));
/* Scan Line should be DWORD aligned and the length is in bytes */
ScanLineSize = ((((WORD)width * (WORD)i) + 31)/32) * 4;
/* Allocate memory */
dwImgSize = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)InfoSize +
(DWORD)ScanLineSize * (DWORD)height;
hLink = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, dwImgSize);
if (!hLink || (!(lpLink = (LPBYTE)GlobalLock(hLink)))) {
SimpleMessage(IDSNoMemAvail, fileName, MB_OK | MB_ICONEXCLAMATION);
goto error2;
}
hbmInfo = GlobalAlloc(GHND, InfoSize);
if (!hbmInfo || (!(lpbmInfo = (LPBITMAPINFO)GlobalLock(hbmInfo)))) {
SimpleMessage(IDSNoMemAvail, fileName, MB_OK | MB_ICONEXCLAMATION);
goto error2;
}
lpHdr = (LPBITMAPFILEHEADER)lpLink;
lpInfo = (LPBITMAPINFO)(lpLink + sizeof(BITMAPFILEHEADER));
lpBits = (LPBYTE)(lpLink + sizeof(BITMAPFILEHEADER) + InfoSize);
/* fill in image header */
lpbmInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
lpbmInfo->bmiHeader.biWidth = width;
lpbmInfo->bmiHeader.biHeight = height;
lpbmInfo->bmiHeader.biPlanes = 1;
lpbmInfo->bmiHeader.biBitCount = (WORD)i;
lpbmInfo->bmiHeader.biCompression =
lpbmInfo->bmiHeader.biClrUsed =
lpbmInfo->bmiHeader.biClrImportant = 0;
lpbmInfo->bmiHeader.biSizeImage = 0;
lpHdr->bfOffBits = sizeof(BITMAPFILEHEADER) + InfoSize;
lpbmInfo->bmiHeader.biXPelsPerMeter = PelsPerLogMeter(hDC ? hDC : fileDC,TRUE);
lpbmInfo->bmiHeader.biYPelsPerMeter = PelsPerLogMeter(hDC ? hDC : fileDC,FALSE);
if (!hDC) {
int ht;
for (ht = height, fileBitmap = NULL; ht && !fileBitmap; ) {
if (!(fileBitmap = CreateBitmap(width, ht, (BYTE)imagePlanes,
(BYTE)imagePixels, NULL)))
ht = ht >> 1;
}
if (!ht) {
PbrushOkError(IDSNotEnufMem, MB_ICONHAND);
goto error2;
}
lpbmInfo->bmiHeader.biHeight = ht;
for (i = height; i; i -= ht) {
if (ht > i)
lpbmInfo->bmiHeader.biHeight = ht = i;
if(!(hOldBitmap = SelectObject(fileDC, fileBitmap))) {
SimpleMessage(IDSUnableSave, fileName, MB_OK | MB_ICONEXCLAMATION);
goto error3;
}
BitBlt(fileDC, 0, 0, width, ht,
hdcWork, rc.left, rc.top + (i - ht), SRCCOPY);
if(!SelectObject(fileDC, hOldBitmap)) {
SimpleMessage(IDSUnableSave, fileName, MB_OK | MB_ICONEXCLAMATION);
goto error3;
}
GetDIBits(fileDC, fileBitmap, 0, ht, lpBits, lpbmInfo, DIB_RGB_COLORS);
hpBits = lpBits;
hpBits += (DWORD)ht * (DWORD)ScanLineSize;
lpBits = hpBits;
}
lpbmInfo->bmiHeader.biHeight = height;
} else
GetDIBits(hDC, hBitmap, 0, height, lpBits, lpbmInfo, DIB_RGB_COLORS);
lpHdr->bfSize = dwImgSize;
lpHdr->bfType = DIBID;
lpHdr->bfReserved1 = lpHdr->bfReserved2 = 0;
lpbmInfo->bmiHeader.biSizeImage = (DWORD)height * (DWORD)ScanLineSize;
RepeatMove(lpInfo,lpbmInfo,InfoSize);
error = FALSE;
error3:
if (!hDC && hOldBitmap)
SelectObject(fileDC, hOldBitmap);
if (!hDC && fileBitmap)
DeleteObject(fileBitmap);
error2:
if (lpLink)
GlobalUnlock(hLink);
if (lpbmInfo)
GlobalUnlock(hbmInfo);
if (hbmInfo) {
GlobalFree(hbmInfo);
hbmInfo = NULL;
}
if (error && hLink) {
GlobalFree(hLink);
hLink = NULL;
}
if (!hDC) {
if (fileDC) {
if (hPalette && hOldPalette)
SelectPalette(hDC? hDC :fileDC, hOldPalette, 0);
DeleteDC(fileDC);
}
}
error1:
SetCursor(hOldCursor);
return hLink;
}
BOOL PutNative(PITEM pitem, HWND hWnd, HANDLE hdata) {
LPBYTE lpNative;
LPBITMAPFILEHEADER lphdr;
BITMAPINFO UNALIGNED * lphdrInfo;
LPBITMAPINFO lpDIBinfo = NULL; /* needed for alignment */
BOOL error = TRUE;
int wplanes, wbitpx, i;
HANDLE hDIBinfo = NULL;
HDC hdc = NULL, parentdc = NULL;
HBITMAP hbitmap = NULL, htempbit = NULL;
DWORD dwSize, dwNumColors;
HCURSOR oldCsr;
UINT errmsg, wSize;
UINT wUsage;
HPALETTE hNewPal = NULL;
LPBYTE lpTemp;
int rc;
BYTE huge *hpTemp;
int ht;
if (!(lpNative = GlobalLock(hdata))) {
errmsg = IDSUnableHdr;
return TRUE;
}
lphdr = (LPBITMAPFILEHEADER)lpNative;
lphdrInfo = (BITMAPINFO UNALIGNED *)(lpNative + sizeof(BITMAPFILEHEADER));
if (lphdrInfo->bmiHeader.biPlanes != 1 || lphdr->bfType != DIBID) {
errmsg = IDSUnableHdr;
goto error1;
}
if (lphdrInfo->bmiHeader.biCompression) {
errmsg = IDSUnknownFmt;
goto error1;
}
if (!(dwNumColors = lphdrInfo->bmiHeader.biClrUsed))
if (lphdrInfo->bmiHeader.biBitCount != 24)
dwNumColors = (1L << lphdrInfo->bmiHeader.biBitCount);
if (!(parentdc = GetDisplayDC(hWnd))) {
errmsg = IDSCantAlloc;
goto error1;
}
if (lphdrInfo->bmiHeader.biBitCount != 1) {
wplanes = GetDeviceCaps(parentdc, PLANES);
wbitpx = GetDeviceCaps(parentdc, BITSPIXEL);
} else {
wplanes = 1;
wbitpx = 1;
}
oldCsr = SetCursor(LoadCursor(NULL, IDC_WAIT));
/* Create a new image with the new sizes, etc. */
nNewImageWidth = LOWORD(lphdrInfo->bmiHeader.biWidth);
nNewImageHeight = LOWORD(lphdrInfo->bmiHeader.biHeight);
nNewImagePlanes = wplanes;
nNewImagePixels = wbitpx;
rc = AllocImg(nNewImageWidth, nNewImageHeight,
nNewImagePlanes, nNewImagePixels, FALSE);
dwSize = sizeof(BITMAPINFOHEADER)
+ dwNumColors * sizeof(RGBQUAD);
if (!(hDIBinfo = GlobalAlloc(GMEM_MOVEABLE, dwSize))) {
errmsg = IDSCantAlloc;
goto error2;
}
if (!(lpDIBinfo = (LPBITMAPINFO) GlobalLock(hDIBinfo))) {
errmsg = IDSCantAlloc;
goto error3;
}
/* copy header into allocated memory */
RepeatMove((LPBYTE)lpDIBinfo, (LPBYTE)lphdrInfo, (WORD)dwSize);
hNewPal = MakeImagePalette(hPalette, hDIBinfo, &wUsage);
if (hNewPal && hNewPal != hPalette) {
SelectPalette(hdcWork, hNewPal, 0);
RealizePalette(hdcWork);
SelectPalette(hdcImage, hNewPal, 0);
RealizePalette(hdcImage);
#ifdef WANT_RIPS
DeleteObject(hPalette);
#endif
hPalette = hNewPal;
}
hdc = CreateCompatibleDC(parentdc);
ReleaseDC(hWnd, parentdc);
parentdc = NULL;
if (!hdc) {
errmsg = IDSNoMemAvail;
goto error4;
}
for (ht = nNewImageHeight, hbitmap = NULL; ht && !hbitmap; ) {
if (!(hbitmap = CreateBitmap(nNewImageWidth, ht,
(BYTE) imagePlanes, (BYTE) imagePixels,
NULL)))
ht = ht >> 1;
}
if (!ht) {
errmsg = IDSNoMemAvail;
goto error5;
}
if (hPalette) {
SelectPalette(hdc, hPalette, FALSE);
RealizePalette(hdc);
}
wSize = ((nNewImageWidth
* lphdrInfo->bmiHeader.biBitCount + 31) & (-32)) >> 3;
lpTemp = lpNative + sizeof(BITMAPFILEHEADER) + dwSize;
error = FALSE;
if (!(htempbit = SelectObject(hdc, hbitmap))) {
errmsg = IDSNoMemAvail;
goto error6;
}
lpDIBinfo->bmiHeader.biHeight = ht;
for (i = nNewImageHeight; i; i -= ht) {
if (i < ht)
lpDIBinfo->bmiHeader.biHeight = ht = i;
if(!SelectObject(hdc, htempbit)) {
errmsg = IDSNoMemAvail;
goto error6;
}
if(!SetDIBits(hdc, hbitmap, 0, ht, lpTemp, lpDIBinfo, wUsage)) {
errmsg = IDSNoMemAvail;
error = TRUE;
break;
}
if(!SelectObject(hdc, hbitmap)) {
errmsg = IDSNoMemAvail;
goto error6;
}
BitBlt(hdcWork, 0, i - ht, nNewImageWidth, ht,
hdc, 0, 0, SRCCOPY);
hpTemp = lpTemp;
hpTemp += (DWORD)ht * (DWORD)wSize;
lpTemp = hpTemp;
}
/* Copy the work bitmap into the undo bitmap */
BitBlt(hdcImage, 0, 0, nNewImageWidth, nNewImageHeight,
hdcWork, 0, 0, SRCCOPY);
wFileType = GetImageFileType(lphdrInfo->bmiHeader.biBitCount);
if (error)
ClearImg();
imageFlag = FALSE; /* Doesn't need saving */
NewImage(rc);
/* Fix the item dimensions */
SetRect(&(pitem->rc), 0, 0, nNewImageWidth, nNewImageHeight);
if (!error)
GetCurrentDirectory(PATHlen, filePath);
error6:
if (htempbit)
SelectObject(hdc, htempbit);
DeleteObject(hbitmap);
error5:
DeleteDC(hdc);
error4:
GlobalUnlock(hDIBinfo);
error3:
GlobalFree(hDIBinfo);
error2:
SetCursor(oldCsr);
if (parentdc)
ReleaseDC(hWnd, parentdc);
error1:
GlobalUnlock(hdata);
return error;
}
PITEM AddItem(PITEM pitem) {
int i;
HANDLE hitem;
i = FndItem((PITEM)pitem);
if (i < cItems) {
vpitem[i]->ref++;
/* Free the duplicate item */
GlobalUnlock(hitem = pitem->hitem);
GlobalFree(hitem);
} else {
if (i < CMAXITEMS) {
vpitem[cItems] = (PITEM)pitem;
vpitem[cItems++]->ref = 1;
} else
return NULL;
}
return vpitem[i];
}
BOOL DeleteItem(PITEM pitem) {
int i;
i = FndItem(pitem);
if (i < cItems && vpitem[i]->ref)
vpitem[i]->ref--;
else
return FALSE;
/* Remove the item from the item table */
if (!vpitem[i]->ref) {
GlobalUnlock(vpitem[i]->hitem);
GlobalFree(vpitem[i]->hitem);
for (i++; i < cItems; i++)
vpitem[i - 1] = vpitem[i];
cItems--;
}
return TRUE;
}
int FndItem(PITEM pitem) {
BOOL fFound;
int i;
fFound = FALSE;
for (i = 0; i < cItems && !fFound;) {
if (pitem->aName == vpitem[i]->aName) {
fFound = TRUE;
} else i++;
}
return i;
}
void ScanRect(LPTSTR lpstr, LPRECT lprc) {
TCHAR Buf[40];
LPTSTR lpstrBuf = Buf;
lstrcpy(Buf, lpstr);
GetNum(&lpstrBuf, (LPINT)&(lprc->left));
GetNum(&lpstrBuf, (LPINT)&(lprc->top));
GetNum(&lpstrBuf, (LPINT)&(lprc->right));
GetNum(&lpstrBuf, (LPINT)&(lprc->bottom));
}
int OutRect(LPTSTR lpstr, int cb, RECT rc) {
TCHAR Buf[40];
int cch;
wsprintf(Buf, TEXT("%d %d %d %d"), rc.left, rc.top, rc.right, rc.bottom);
if ((cch = lstrlen(Buf)) > cb)
Buf[cch = cb] = 0;
lstrcpy(lpstr, Buf);
return cch;
}
#define CBLINKMAX 128
HANDLE GetLink(RECT rc) {
TCHAR pchlink[CBLINKMAX];
int cblink;
#ifndef OLE_20
int cchLink;
#endif
HANDLE hlink;
POLESTR lplink;
/* Link data... (PBrush\0<Doc name>\0<Item name>\0\0) */
lstrcpy(pchlink, pgmName);
cblink = lstrlen(pchlink) + 1;
/* Copy filePath\fileName */
lstrcpy((LPTSTR)(pchlink + cblink), filePath);
if (filePath[lstrlen(filePath)-1] != TEXT('\\'))
lstrcat(pchlink + cblink, TEXT("\\"));
lstrcat(pchlink + cblink, fileName);
cblink += lstrlen(pchlink + cblink) + 1;
cblink += (int)OutRect(pchlink + cblink, CBLINKMAX - cblink, rc) + 1;
pchlink[cblink++] = (TCHAR) 0; /* throw in another NULL at the end */
#ifndef OLE_20
cchLink = cblink;
cblink = WideCharToMultiByte(CP_ACP, 0, pchlink, cchLink, NULL, 0,
NULL, NULL);
#else
cblink *= sizeof(TCHAR);
#endif
hlink = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, cblink);
if (hlink) {
if (lplink = (POLESTR)GlobalLock(hlink)) {
#ifndef OLE_20
WideCharToMultiByte(CP_ACP, 0, pchlink, cchLink, lplink, cblink,
NULL, NULL);
#else
RepeatMove(lplink, pchlink, (WORD)cblink);
#endif
GlobalUnlock(hlink);
} else {
GlobalFree(hlink);
hlink = NULL;
}
}
return hlink;
}
HBITMAP GetBitmap(PITEM pitem) {
HDC hdcmem;
HBITMAP hbitmap;
HBITMAP holdbitmap;
int cxBitmap;
int cyBitmap;
cxBitmap = (pitem->rc.right - pitem->rc.left);
cyBitmap = (pitem->rc.bottom - pitem->rc.top);
hdcmem = CreateCompatibleDC(NULL);
hbitmap = CreateBitmap(cxBitmap, cyBitmap,
(BYTE)imagePlanes, (BYTE)imagePixels, 0);
holdbitmap = SelectObject(hdcmem, hbitmap);
MSetWindowOrg(hdcmem, 0, 0);
MSetWindowExt(hdcmem, cxBitmap, cyBitmap);
/* Paint directly into the BITMAP */
BitBlt(hdcmem, 0, 0, cxBitmap, cyBitmap,
hdcWork, pitem->rc.left, pitem->rc.top, SRCCOPY);
hbitmap = SelectObject(hdcmem, holdbitmap);
DeleteDC(hdcmem);
return hbitmap;
}
HANDLE GetMF(HDC hDC, HBITMAP hBitmap, RECT rc) {
BOOL fCreatedDC = FALSE;
BOOL fError = TRUE;
HANDLE hmfpict = NULL;
HBITMAP hbm = NULL;
HBITMAP hbmOld = NULL;
HPALETTE hOldPalette = NULL, hDefPalette = NULL;
HDC hdcMF = NULL;
HDC hdcWnd = NULL;
HWND hwndFrame = pbrushWnd[PARENTid];
LPMETAFILEPICT lpmfpict = NULL;
int cxImage;
int cyImage;
/* Compute the image size */
cxImage = rc.right - rc.left;
cyImage = rc.bottom - rc.top;
/* Get the window DC */
if (!(hdcWnd = GetDC(hwndFrame)))
goto Error;
if (!hDC) {
fCreatedDC = TRUE;
/* Make a DC compatible to the window DC, and initialize a bitmap. */
if (!(hDC = CreateCompatibleDC(NULL))
|| !(hbm = CreateCompatibleBitmap(hdcWnd, cxImage, cyImage))
|| (hPalette && !(hOldPalette = SelectPalette(hDC, hPalette, 0)))
|| !(hbmOld = SelectObject(hDC, hbm)))
goto Error;
if (hPalette)
RealizePalette(hDC);
/* Draw the image... */
BitBlt(hDC, 0, 0, cxImage, cyImage,
hdcWork, rc.left, rc.top, SRCCOPY);
} else
{
if (hPalette) {
hOldPalette = SelectPalette(hDC, hPalette, 0);
RealizePalette(hDC);
}
hbmOld = SelectObject(hDC, hBitmap);
}
/* Create the metafile */
if (!(hmfpict = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, sizeof(METAFILEPICT)))
|| !(lpmfpict = (LPMETAFILEPICT)GlobalLock(hmfpict))
|| !(hdcMF = CreateMetaFile(NULL)))
goto Error;
/* Initialize the metafile */
MSetWindowOrg(hdcMF, 0, 0);
MSetWindowExt(hdcMF, cxImage, cyImage);
if (hPalette)
{
SelectPalette(hdcMF, hPalette, TRUE);
RealizePalette(hdcMF);
}
/* ... and then write it out to the metafile. */
StretchBlt(hdcMF, 0, 0, cxImage, cyImage,
hDC, 0, 0, cxImage, cyImage, SRCCOPY);
if (hDefPalette = GetStockObject(DEFAULT_PALETTE))
{
SelectPalette(hdcMF, hDefPalette, TRUE);
//RealizePalette(hdcMF);
}
/* Finish filling in the metafile header */
lpmfpict->mm = MM_ANISOTROPIC;
lpmfpict->xExt = PelsToLogHimetric(hdcWnd,TRUE,cxImage);
lpmfpict->yExt = PelsToLogHimetric(hdcWnd,FALSE,cyImage);
ReleaseDC(hwndFrame, hdcWnd);
hdcWnd = NULL;
lpmfpict->hMF = CloseMetaFile(hdcMF);
fError = FALSE;
Error:
if (lpmfpict)
GlobalUnlock(hmfpict);
if (hbmOld)
SelectObject(hDC, hbmOld);
if (hbm)
DeleteObject(hbm);
if (hOldPalette)
{
SelectPalette(hDC, hOldPalette, 0);
RealizePalette(hDC);
}
if (fCreatedDC && hDC)
DeleteDC(hDC);
if (hdcWnd)
ReleaseDC(hwndFrame, hdcWnd);
/* If we had an error, return NULL */
if (fError && hmfpict) {
GlobalFree(hmfpict);
hmfpict = NULL;
}
return hmfpict;
}
/* Change menu item from Save to Update */
void FixMenus(void) {
HMENU hMenu = GetMenu(pbrushWnd[PARENTid]);
TCHAR szTemp[CBMENUITEMMAX];
/* Fix the menu bar items */
LoadString(hInst, IDS_UPDATE, szTemp, CharSizeOf(szTemp));
ChangeMenuItem(FILEsave, FILEupdate, szTemp);
vfIsLink = FALSE;
}
/* Change menu item from Update to Save
* and "Exit & Return to xxx" to "Exit" */
void FAR UnfixMenus(void) {
HMENU hMenu = GetMenu(pbrushWnd[PARENTid]);
TCHAR szMenuStr[CBMENUITEMMAX];
/* Fix the menu bar items */
LoadString(hInst, IDS_SAVE, szMenuStr, CharSizeOf(szMenuStr));
ChangeMenuItem(FILEupdate, FILEsave, szMenuStr);
LoadString(hInst, IDSuntitled, noFile, CharSizeOf(noFile));
LoadString(hInst, IDS_EXIT, szMenuStr, CharSizeOf(szMenuStr));
ChangeMenuItem(FILEexit, FILEexit, szMenuStr);
vfIsLink = TRUE;
}
void GetNum(LPTSTR FAR *lplpstrBuf, int FAR *lpint) {
*lpint = 0;
while (TEXT('0') <= **lplpstrBuf && **lplpstrBuf <= TEXT('9')) {
*lpint = *lpint * 10 + (**lplpstrBuf - TEXT('0'));
(*lplpstrBuf)++;
}
while (**lplpstrBuf && **lplpstrBuf == TEXT(' '))
(*lplpstrBuf)++;
}
//int WINAPI MultDiv(int,int,int);
#define nPelsPerLogInch GetDeviceCaps(hDC, bHoriz ? LOGPIXELSX : LOGPIXELSY)
int PelsPerLogMeter(HDC hDC,BOOL bHoriz)
{
#define nMMPerMeterTimes10 10000
#define nMMPerInchTimes10 254
return MulDiv(nPelsPerLogInch, nMMPerMeterTimes10, nMMPerInchTimes10);
}
int PelsToLogHimetric(HDC hDC,BOOL bHoriz, int pels)
{
#define nHMPerInch 2540
return MulDiv(pels,nHMPerInch,nPelsPerLogInch);
}