mirror of https://github.com/lianthony/NT4.0
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.
1445 lines
42 KiB
1445 lines
42 KiB
#include "precomp.h"
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* Windows Cardfile - Written by Mark Cliggett */
|
|
/* (c) Copyright Microsoft Corp. 1985, 1994 - All Rights Reserved */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
#ifndef WIN32
|
|
#define RINT int
|
|
#else
|
|
#define RINT short
|
|
typedef struct _rrect
|
|
{
|
|
RINT left, top, right, bottom ;
|
|
} RRECT ;
|
|
#endif
|
|
/* This file contains all the picture operations. It virtualizes the
|
|
* interface so we deal with pictures instead of old Bitmaps and objects.
|
|
*
|
|
* If the picture is a Linked or Embedded object, the OLE client DLL
|
|
* will be called. Otherwise, we will process the data as we did for
|
|
* Windows 3.0.
|
|
*
|
|
*/
|
|
|
|
|
|
BOOL fCreateFromFile;
|
|
BYTE *vpfbmp;
|
|
DWORD vcbLeftToRead;
|
|
DWORD vcLeft;
|
|
FAKEBITMAP vfbmp;
|
|
HCURSOR hcurOle = NULL;
|
|
HWND hwndError;
|
|
LPCARDSTREAM lpStream = NULL;
|
|
LPOLECLIENT lpclient = NULL;
|
|
LPOLEOBJECT lpObjectUndo = NULL;
|
|
OBJECTTYPE otObjectUndo = 0 ;
|
|
WORD cWait = 0;
|
|
TCHAR szClip[] = TEXT("Clipboard");
|
|
|
|
|
|
/* szObjectName if szObjFormat with expanded INT number */
|
|
#ifndef OLE_20
|
|
|
|
CHAR szUndo[] = "Undo";
|
|
CHAR szObjectName[OBJNAMEMAX + 10];
|
|
CHAR szObjFormat[OBJNAMEMAX];
|
|
|
|
#else
|
|
|
|
TCHAR szUndo[] = TEXT("Undo");
|
|
TCHAR szObjectName[OBJNAMEMAX + 10];
|
|
TCHAR szObjFormat[OBJNAMEMAX];
|
|
|
|
#endif
|
|
|
|
int iPos ;
|
|
|
|
NOEXPORT void NEAR SetFile(HANDLE fh);
|
|
DWORD (pascal far *pfOldRead) (LPOLESTREAM, LPBYTE, DWORD);
|
|
DWORD (pascal far *pfNewRead) (LPOLESTREAM, LPBYTE, DWORD);
|
|
|
|
void PicDelete(PCARD pCard)
|
|
{
|
|
if (pCard->lpObject) {
|
|
#if !defined(WIN32)
|
|
if (HIWORD(pCard->lpObject)) {
|
|
#else
|
|
if (GetObjectType(pCard->lpObject) != OBJ_BITMAP) {
|
|
#endif
|
|
WaitForObject(pCard->lpObject);
|
|
/* OleRelease() because the object is still
|
|
* part of the Card File.
|
|
*/
|
|
switch (OleError(OleRelease(pCard->lpObject)))
|
|
{
|
|
case FOLEERROR_NOTGIVEN:
|
|
ErrorMessage(E_FAILED_TO_DELETE_OBJECT);
|
|
break;
|
|
#if 0
|
|
case FOLEERROR_GIVEN:
|
|
break;
|
|
#endif
|
|
case FOLEERROR_OK:
|
|
InvalidateRect(hEditWnd, NULL, TRUE);
|
|
WaitForObject(pCard->lpObject);
|
|
break;
|
|
}
|
|
} else
|
|
#if !defined(WIN32)
|
|
DeleteObject((HBITMAP)LOWORD(pCard->lpObject));
|
|
#else
|
|
DeleteObject((HBITMAP)(pCard->lpObject));
|
|
#endif
|
|
}
|
|
pCard->lpObject = NULL;
|
|
|
|
}
|
|
|
|
/* SIDE EFFECT: Advances the file pointer past the object */
|
|
BOOL PicRead(PCARD pCard, HANDLE fh, BOOL fOld)
|
|
{
|
|
RINT bmSize;
|
|
RINT cxBitmap;
|
|
RINT cyBitmap;
|
|
RINT cEighths;
|
|
OLESTATUS olestat;
|
|
LPOLEOBJECT lpObject = NULL;
|
|
DWORD idObject;
|
|
|
|
MyByteReadFile(fh, &bmSize, sizeof(RINT));
|
|
|
|
/* Does the card contain a picture? */
|
|
if (!bmSize) { /* No... */
|
|
pCard->lpObject = NULL;
|
|
return TRUE; /* Succeeded in reading 0 size object */
|
|
}
|
|
|
|
if (fOLE) /* Reading a new file... */
|
|
{
|
|
unsigned long fhLoc;
|
|
|
|
SetFile(fh);
|
|
|
|
if (fOld) /* Set up to read from old format card */
|
|
{
|
|
lpStream->lpstbl->Get = pfOldRead;
|
|
vcbLeftToRead = ((DWORD)bmSize);
|
|
}
|
|
else
|
|
MyByteReadFile(fh, &idObject, sizeof(DWORD));
|
|
|
|
/* Save current position of file pointer */
|
|
if ((fhLoc = MyFileSeek(fh, 0L, 1)) == -1)
|
|
return FALSE;
|
|
|
|
/* Synchronously: Load the new object */
|
|
#ifndef OLE_20
|
|
wsprintfA (szObjectName, szObjFormat, idObject + 1);
|
|
#else
|
|
wsprintfW (szObjectName, szObjFormat, idObject + 1);
|
|
#endif
|
|
olestat = OleLoadFromStream ((LPOLESTREAM)lpStream, szPStdFile,
|
|
lpclient, lhcdoc, szObjectName, &lpObject);
|
|
|
|
if (olestat == OLE_WAIT_FOR_RELEASE)
|
|
{
|
|
cOleWait++;
|
|
WaitForObject (lpObject);
|
|
olestat = oleloadstat;
|
|
}
|
|
|
|
if (OleError(olestat))
|
|
{
|
|
/* Reset file pointer, and try again */
|
|
vcbLeftToRead = ((DWORD)bmSize);
|
|
SetFile(fh);
|
|
if (MyFileSeek(fh, fhLoc, 0) == -1)
|
|
return FALSE;
|
|
|
|
/* Synchronously: Read it with the "Static" protocol */
|
|
olestat = OleLoadFromStream ((LPOLESTREAM)lpStream, szPStatic,
|
|
lpclient, lhcdoc, szObjectName, &lpObject);
|
|
|
|
if (olestat == OLE_WAIT_FOR_RELEASE)
|
|
{
|
|
cOleWait++;
|
|
WaitForObject (lpObject);
|
|
olestat = oleloadstat;
|
|
}
|
|
|
|
if (OleError(olestat))
|
|
{
|
|
lpStream->lpstbl->Get = pfNewRead; /* Restore */
|
|
return FALSE;
|
|
}
|
|
}
|
|
pCard->lpObject = lpObject;
|
|
|
|
if (fOld)
|
|
{
|
|
/* Side effect: pCard->rcObject has already been filled in */
|
|
pCard->otObject = STATIC;
|
|
MyFileSeek (fh, vcbLeftToRead, 1); /* For Video 7 bug */
|
|
lpStream->lpstbl->Get = pfNewRead; /* Restore so new is fastest */
|
|
pCard->idObject = idObjectMax++;
|
|
}
|
|
else
|
|
{
|
|
RINT cx;
|
|
RINT cy;
|
|
|
|
/* Read the character size when saving, and scale to the
|
|
* current character size.
|
|
*/
|
|
MyByteReadFile (fh, &cx, sizeof(RINT));
|
|
MyByteReadFile (fh, &cy, sizeof(RINT));
|
|
#ifndef WIN32
|
|
MyByteReadFile (fh, &(pCard->rcObject), sizeof(RECT));
|
|
#else
|
|
{
|
|
RRECT rrec;
|
|
|
|
MyByteReadFile(fh, &(rrec), 8) ;
|
|
SetRect (&(pCard->rcObject), (LONG)rrec.left, (LONG)rrec.top,
|
|
(LONG)rrec.right, (LONG)rrec.bottom);
|
|
}
|
|
#endif
|
|
|
|
/* Character width differs, scale in the x direction */
|
|
if (cx != (RINT)CharFixWidth)
|
|
{
|
|
pCard->rcObject.left = Scale(pCard->rcObject.left, CharFixWidth, cx);
|
|
pCard->rcObject.right = Scale(pCard->rcObject.right, CharFixWidth, cx);
|
|
}
|
|
|
|
/* Character height differs, scale in the y direction */
|
|
if (cy != (RINT)CharFixHeight)
|
|
{
|
|
pCard->rcObject.top = Scale(pCard->rcObject.top, CharFixHeight, cy);
|
|
pCard->rcObject.bottom = Scale(pCard->rcObject.bottom, CharFixHeight, cy);
|
|
}
|
|
|
|
/* Retrieve the object type */
|
|
MyByteReadFile (fh, &(pCard->otObject), sizeof(OBJECTTYPE));
|
|
pCard->idObject = idObject;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HANDLE hBits;
|
|
LPBYTE lpBits;
|
|
|
|
if (!fOld) /* No OLE, can't read new objects! */
|
|
{
|
|
pCard->lpObject = NULL;
|
|
ErrorMessage(E_NEW_FILE_NOT_READABLE);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Read in phony monochrome BITMAP header */
|
|
MyByteReadFile(fh, &cxBitmap, sizeof(RINT));
|
|
MyByteReadFile(fh, &cyBitmap, sizeof(RINT));
|
|
|
|
MyByteReadFile(fh, &cEighths, sizeof(RINT));
|
|
pCard->rcObject.left = (cEighths * CharFixWidth) / 8;
|
|
pCard->rcObject.right = pCard->rcObject.left + cxBitmap - 1;
|
|
|
|
MyByteReadFile(fh, &cEighths, sizeof(RINT));
|
|
pCard->rcObject.top = (cEighths * CharFixHeight) / 8;
|
|
pCard->rcObject.bottom = pCard->rcObject.top + cyBitmap - 1;
|
|
pCard->idObject = idObjectMax++;
|
|
|
|
/* Read in the BITMAP bits */
|
|
if (hBits = GlobalAlloc(GHND, (WORD)bmSize))
|
|
{
|
|
if (lpBits = (LPBYTE)GlobalLock(hBits))
|
|
{
|
|
MyByteReadFile(fh, lpBits, bmSize);
|
|
/* Make the selector zero */
|
|
pCard->lpObject = (LPOLEOBJECT) MAKELONG(
|
|
CreateBitmap(cxBitmap, cyBitmap, 1, 1, lpBits), 0);
|
|
GlobalUnlock(hBits);
|
|
}
|
|
GlobalFree(hBits);
|
|
}
|
|
else /* Skip past the object */
|
|
MyFileSeek(fh, (unsigned long)bmSize, 1);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* If fForceOld is specified, or the OLE library isn't loaded,
|
|
* PicWrite() will write new format files.
|
|
*/
|
|
|
|
/* SIDE EFFECT: moves pointer to end of written object */
|
|
BOOL PicWrite(PCARD pCard, HANDLE fh, BOOL fForceOld) {
|
|
HANDLE hBitmap = NULL;
|
|
RINT bmSize;
|
|
RINT bmWidth;
|
|
RINT bmHeight;
|
|
RINT cEighths;
|
|
HANDLE hBits = NULL;
|
|
LPBYTE lpBits = NULL;
|
|
|
|
if (fOLE)
|
|
{
|
|
if (fForceOld)
|
|
{
|
|
/* Convert picture to monochrome bitmap (0 colors) */
|
|
hBitmap = MakeObjectCopy(pCard, (HDC)NULL);
|
|
goto OldWrite;
|
|
}
|
|
else
|
|
{
|
|
/* Write a BOOL so that cardfiles can be compared */
|
|
bmSize = (RINT)!!pCard->lpObject;
|
|
|
|
if (!MyByteWriteFile(fh, &bmSize, sizeof(RINT)))
|
|
goto Disk_Full;
|
|
|
|
if (bmSize)
|
|
{
|
|
SetFile(fh);
|
|
if (!MyByteWriteFile(fh, &(pCard->idObject), sizeof(DWORD)))
|
|
goto Disk_Full;
|
|
|
|
if (OLE_OK != OleSaveToStream(pCard->lpObject, (LPOLESTREAM)lpStream))
|
|
goto Disk_Full;
|
|
|
|
/* Write current character size, rectangle, and object type.
|
|
*/
|
|
#ifndef WIN32
|
|
if (!MyByteWriteFile(fh, &CharFixWidth, sizeof(RINT))
|
|
|| !MyByteWriteFile(fh, &CharFixHeight, sizeof(RINT))
|
|
|| !MyByteWriteFile(fh, &(pCard->rcObject), sizeof(RECT))
|
|
|| !MyByteWriteFile(fh, &(pCard->otObject), sizeof(OBJECTTYPE)))
|
|
{
|
|
goto Disk_Full;
|
|
}
|
|
#else
|
|
if (!MyByteWriteFile(fh, &CharFixWidth, sizeof(RINT))
|
|
|| !MyByteWriteFile(fh, &CharFixHeight, sizeof(RINT)))
|
|
goto Disk_Full;
|
|
|
|
{
|
|
RRECT rrec;
|
|
|
|
rrec.left = (short)(pCard->rcObject).left ;
|
|
rrec.right = (short)(pCard->rcObject).right ;
|
|
rrec.top = (short)(pCard->rcObject).top ;
|
|
rrec.bottom = (short)(pCard->rcObject).bottom ;
|
|
|
|
if(!MyByteWriteFile(fh, &(rrec), 8))
|
|
goto Disk_Full ;
|
|
|
|
if(!MyByteWriteFile(fh, &(pCard->otObject), sizeof(OBJECTTYPE)))
|
|
goto Disk_Full;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
else /* Can only write the old format (sigh) */
|
|
{
|
|
OldWrite:
|
|
if (!hBitmap)
|
|
#if !defined(WIN32)
|
|
hBitmap = (HBITMAP)LOWORD(pCard->lpObject);
|
|
#else
|
|
hBitmap = (HBITMAP)(pCard->lpObject);
|
|
#endif
|
|
|
|
if (hBitmap)
|
|
{
|
|
/* Calculate the BITMAP dimensions */
|
|
bmWidth = (RINT)((pCard->rcObject.right - pCard->rcObject.left) + 1);
|
|
bmHeight = (RINT)((pCard->rcObject.bottom - pCard->rcObject.top) + 1);
|
|
bmSize = (RINT)((((bmWidth + 0x000f) >> 4) << 1) * bmHeight);
|
|
|
|
if ((hBits = GlobalAlloc(GHND, (WORD)bmSize))
|
|
&& (lpBits = (LPBYTE)GlobalLock(hBits)))
|
|
{
|
|
/* Write out the size, width, height */
|
|
if (!MyByteWriteFile(fh, &bmSize, sizeof(RINT)) ||
|
|
!MyByteWriteFile(fh, &bmWidth, sizeof(RINT)) ||
|
|
!MyByteWriteFile(fh, &bmHeight, sizeof(RINT)))
|
|
goto Disk_Full;
|
|
|
|
/* Write out the x and y positions */
|
|
cEighths = (RINT)((pCard->rcObject.left * 8) / CharFixWidth);
|
|
if (!MyByteWriteFile(fh, &cEighths, sizeof(RINT)))
|
|
goto Disk_Full;
|
|
|
|
cEighths = (RINT)((pCard->rcObject.top * 8) / CharFixHeight);
|
|
if (!MyByteWriteFile(fh, &cEighths, sizeof(RINT)))
|
|
goto Disk_Full;
|
|
|
|
/* Write out the actual BITMAP bits */
|
|
GetBitmapBits(hBitmap, (unsigned long)bmSize, lpBits);
|
|
if (!MyByteWriteFile(fh, lpBits, bmSize))
|
|
goto Disk_Full;
|
|
GlobalUnlock(hBits);
|
|
GlobalFree(hBits);
|
|
}
|
|
else
|
|
{
|
|
Disk_Full:
|
|
if (lpBits)
|
|
GlobalUnlock(hBits);
|
|
|
|
if (hBits)
|
|
GlobalFree(hBits);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RINT zero = 0;
|
|
|
|
if (!MyByteWriteFile(fh, &zero, sizeof(RINT)))
|
|
goto Disk_Full;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL PicDraw(PCARD pCard, HDC hDC, BOOL fAtOrigin) {
|
|
BOOL bSuccess;
|
|
HANDLE hOldObject;
|
|
HDC hMemoryDC;
|
|
|
|
/* If we have an object, call OleDraw() */
|
|
if (GetObjectType(pCard->lpObject) != OBJ_BITMAP) {
|
|
HRGN hrgn;
|
|
RECT rc, rcClip;
|
|
POINT pt;
|
|
INT iPrevStretchMode;
|
|
|
|
iPrevStretchMode= SetStretchBltMode( hDC, HALFTONE );
|
|
SetBrushOrgEx( hDC, 0,0, &pt );
|
|
|
|
rc = pCard->rcObject;
|
|
|
|
if (fAtOrigin) /* Move rect to (0,0) */
|
|
OffsetRect(&rc, -rc.left, -rc.top);
|
|
|
|
/* Force OleDraw to draw within the clipping region */
|
|
if (hrgn = CreateRectRgnIndirect(&rc))
|
|
SelectObject(hDC, hrgn);
|
|
|
|
/* Bug 11290: Don't draw outside the edit window's client area
|
|
* 11 January 1992 Clark R. Cyr
|
|
*/
|
|
GetClientRect (hEditWnd, &rcClip);
|
|
IntersectClipRect (hDC, rcClip.left, rcClip.top,
|
|
rcClip.right, rcClip.bottom);
|
|
|
|
/* Draw the object */
|
|
bSuccess = (OLE_OK == OleDraw(pCard->lpObject, hDC, (LPRECT)&rc, NULL, NULL));
|
|
|
|
/* If we had a clipping region, delete it */
|
|
if (hrgn)
|
|
DeleteObject(hrgn);
|
|
|
|
SetStretchBltMode( hDC, iPrevStretchMode );
|
|
SetBrushOrgEx( hDC, pt.x, pt.y, NULL );
|
|
}
|
|
else /* If we have a BITMAP, BitBlt it into the DC */
|
|
{
|
|
if (pCard->lpObject && (hMemoryDC = CreateCompatibleDC(hDC)))
|
|
{
|
|
RINT cxBitmap, cyBitmap;
|
|
|
|
cxBitmap = (RINT)(pCard->rcObject.right - pCard->rcObject.left) + 1,
|
|
cyBitmap = (RINT)(pCard->rcObject.bottom - pCard->rcObject.top) + 1,
|
|
|
|
hOldObject = SelectObject(hMemoryDC, (HBITMAP)(pCard->lpObject));
|
|
BitBlt(hDC, pCard->rcObject.left, pCard->rcObject.top,
|
|
cxBitmap, cyBitmap, hMemoryDC, 0, 0, SRCAND);
|
|
SelectObject(hMemoryDC, hOldObject);
|
|
DeleteDC(hMemoryDC);
|
|
bSuccess = TRUE;
|
|
}
|
|
}
|
|
return bSuccess;
|
|
}
|
|
|
|
void PicCutCopy(PCARD pCard, BOOL fCut)
|
|
{
|
|
/* If no object or we can't open the clipboard, fail */
|
|
if (!pCard->lpObject || !OpenClipboard(hIndexWnd))
|
|
return;
|
|
|
|
EmptyClipboard();
|
|
|
|
Hourglass(TRUE);
|
|
if (GetObjectType(pCard->lpObject) != OBJ_BITMAP) {
|
|
if (OLE_OK != OleCopyToClipboard(pCard->lpObject))
|
|
IndexOkError(EINSMEMORY);
|
|
}
|
|
else if (pCard->lpObject) /* Old BITMAP */
|
|
{
|
|
BITMAP bm;
|
|
HBITMAP hBitmap;
|
|
|
|
GetObject((HBITMAP)(pCard->lpObject), sizeof(BITMAP), (LPVOID)&bm);
|
|
if (!(hBitmap = MakeBitmapCopy((HBITMAP)(pCard->lpObject), &bm, (HDC)NULL )))
|
|
IndexOkError(EINSMEMORY);
|
|
else
|
|
SetClipboardData(CF_BITMAP, hBitmap);
|
|
}
|
|
CloseClipboard();
|
|
|
|
if (fCut && pCard->lpObject) { /* Delete the object */
|
|
/* If Undo object exists, delete it */
|
|
DeleteUndoObject();
|
|
|
|
/* Instead of deleting then cloning, just save the object */
|
|
lpObjectUndo = pCard->lpObject;
|
|
otObjectUndo = pCard->otObject;
|
|
OleRename(lpObjectUndo, szUndo);
|
|
pCard->lpObject = NULL;
|
|
|
|
InvalidateRect(hEditWnd, (LPRECT)&(pCard->rcObject), TRUE);
|
|
CurCardHead.flags |= FDIRTY;
|
|
}
|
|
Hourglass(FALSE);
|
|
}
|
|
|
|
/*
|
|
* Paste/PasteLink an Object
|
|
*
|
|
* pCard - Card where the object should be pasted,
|
|
* fPaste - specifies Paste/PasteLink
|
|
* ClipFormat - Should be NULL for Edit.Paste, Edit.PasteLink
|
|
* - will contain a specific Clipbrd format when user chooses
|
|
* Paste/PasteLink in Edit.PasteSpecial dlg.
|
|
* Parameters for various calls:
|
|
*
|
|
* On Edit.Paste - PicPaste(pCard, TRUE, 0);
|
|
* On Edit.PasteLink - PicPaste(pCard, FALSE, 0);
|
|
* On Paste/PasteLink from PasteSpecial Dlg,
|
|
* if (class name chosen from the Objects list)
|
|
* Similar to Edit.Paste/PasteLink.
|
|
* else if (specific format chosen)
|
|
* {
|
|
* PicPaste(pCard, TRUE, Format);
|
|
* (Paste a static object in given format)
|
|
* OR
|
|
* PasteLink(pCard, FALSE, Format);
|
|
*/
|
|
void PicPaste(
|
|
PCARD pCard,
|
|
BOOL fPaste, /* Paste/PasteLink */
|
|
WORD ClipFormat) /* For Paste from PasteSpecial Dlg, may specify a format */
|
|
{
|
|
LONG objType;
|
|
LPOLEOBJECT lpObject;
|
|
OBJECTTYPE otObject;
|
|
BOOL fError;
|
|
|
|
if (!OpenClipboard(hIndexWnd))
|
|
return; /* Couldn't open the clipboard */
|
|
|
|
Hourglass(TRUE);
|
|
if (fOLE)
|
|
{
|
|
/* Don't replace the current object unless we're successful */
|
|
#ifndef OLE_20
|
|
wsprintfA (szObjectName, szObjFormat, idObjectMax + 1);
|
|
#else
|
|
wsprintfW (szObjectName, szObjFormat, idObjectMax + 1);
|
|
#endif
|
|
if (fPaste)
|
|
{
|
|
if (ClipFormat) /* Paste a specific format (from PasteSpecial Dlg) */
|
|
{
|
|
fError = OleError(OleCreateFromClip(szPStatic, lpclient, lhcdoc, szObjectName,
|
|
&lpObject, olerender_format, ClipFormat));
|
|
}
|
|
else /* Paste from Edit.Paste */
|
|
{
|
|
/* Try StdFileEditing protocol */
|
|
fError = OleError(OleCreateFromClip(szPStdFile, lpclient, lhcdoc, szObjectName,
|
|
&lpObject, olerender_draw, 0));
|
|
/* If unsuccessful, try Static protocol */
|
|
if (fError)
|
|
fError = OleError(OleCreateFromClip(szPStatic, lpclient, lhcdoc, szObjectName,
|
|
&lpObject, olerender_draw, 0));
|
|
}
|
|
} else
|
|
{
|
|
/* create a link, in response to Edit.PasteLink or
|
|
* PasteLink from PasteSpecial dlg
|
|
*/
|
|
if (ClipFormat) /* PasteLink a specific format (from PasteSpecial Dlg) */
|
|
{
|
|
fError = OleError(OleCreateLinkFromClip(szPStdFile, lpclient, lhcdoc, szObjectName,
|
|
&lpObject, olerender_format, ClipFormat));
|
|
}
|
|
else /* PasteLink an object */
|
|
{
|
|
fError = OleError(OleCreateLinkFromClip(szPStdFile, lpclient, lhcdoc, szObjectName,
|
|
&lpObject, olerender_draw, 0));
|
|
}
|
|
}
|
|
if (fError)
|
|
{
|
|
lpObject = NULL;
|
|
if (fError == FOLEERROR_NOTGIVEN)
|
|
ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
|
|
} else
|
|
{
|
|
/* Figure out what kind of object we have, OleCreateFromLink
|
|
* can create an embedded object */
|
|
OleQueryType(lpObject, &objType);
|
|
switch (objType)
|
|
{
|
|
case OT_EMBEDDED: otObject = EMBEDDED; break;
|
|
case OT_LINK: otObject = LINK; break;
|
|
default: otObject = STATIC; break;
|
|
}
|
|
}
|
|
if (lpObject)
|
|
{
|
|
if (pCard->lpObject)
|
|
PicDelete(pCard);
|
|
pCard->lpObject = lpObject;
|
|
pCard->otObject = otObject;
|
|
pCard->idObject = idObjectMax++;
|
|
DoSetHostNames(CurCard.lpObject, CurCard.otObject);
|
|
InvalidateRect(hEditWnd, NULL, TRUE);
|
|
SetRect(&(pCard->rcObject), 0, 0, 0, 0);
|
|
CurCardHead.flags |= FDIRTY;
|
|
}
|
|
}
|
|
else
|
|
{ /* Create an old object the hard way */
|
|
HBITMAP hBitmap;
|
|
BITMAP bm;
|
|
|
|
if (hBitmap = (HBITMAP)GetClipboardData(CF_BITMAP))
|
|
{
|
|
GetObject(hBitmap, sizeof(BITMAP), &bm);
|
|
if (!(hBitmap = MakeBitmapCopy(hBitmap, &bm, (HDC) NULL )))
|
|
IndexOkError(EINSMEMORY);
|
|
else
|
|
{
|
|
if (pCard->lpObject)
|
|
PicDelete(pCard);
|
|
|
|
/* Make the selector zero */
|
|
pCard->lpObject = (LPOLEOBJECT)MAKELONG(hBitmap, 0);
|
|
SetRect(&(pCard->rcObject), 0, 0, bm.bmWidth-1, bm.bmHeight-1);
|
|
InvalidateRect(hEditWnd, (LPRECT)&(pCard->rcObject), TRUE);
|
|
CurCardHead.flags |= FDIRTY;
|
|
}
|
|
}
|
|
}
|
|
CloseClipboard();
|
|
Hourglass(FALSE);
|
|
}
|
|
|
|
/* MakeObjectCopy
|
|
*
|
|
* pCard - card to get object from
|
|
* hDestDC - if present, the format to get, otherwise monochrome
|
|
*
|
|
*/
|
|
|
|
HBITMAP MakeObjectCopy(PCARD pCard, HDC hDestDC )
|
|
{
|
|
HBITMAP hBitmap = NULL;
|
|
HBRUSH hBrush = NULL;
|
|
HDC hDCDest = NULL;
|
|
HDC hDC;
|
|
int cxBitmap;
|
|
int cyBitmap;
|
|
BOOL fError = TRUE;
|
|
HANDLE hObject;
|
|
BITMAP bm;
|
|
SIZE sz ;
|
|
|
|
/* LOWORD(lpObject) is NULL only if no bitmap in 3.0 file */
|
|
if (pCard->lpObject == NULL)
|
|
return NULL;
|
|
|
|
/* First, try to load a normal BITMAP */
|
|
if (GetObjectType(pCard->lpObject) != OBJ_BITMAP)
|
|
{
|
|
if (OLE_OK != OleGetData(pCard->lpObject, CF_BITMAP, &hBitmap))
|
|
hBitmap = NULL;
|
|
}
|
|
else
|
|
{
|
|
hBitmap = (HBITMAP)(pCard->lpObject);
|
|
}
|
|
|
|
/* got a bitmap, either this is a bitmap in OLE object OR
|
|
it is a bitmap in 3.0 card file.
|
|
return a copy of the bitmap */
|
|
if (hBitmap)
|
|
{
|
|
GetObject(hBitmap, sizeof(BITMAP), &bm);
|
|
return MakeBitmapCopy(hBitmap, &bm, hDestDC );
|
|
}
|
|
|
|
/* Ole Object is not a bitmap. May be a metafile or s'thing else.
|
|
Draw it into a mono DC and return a handle to this bitmap */
|
|
Hourglass(TRUE);
|
|
|
|
/* If we don't succeed, draw the picture into a monochrome DC */
|
|
if( hDestDC == NULL )
|
|
{
|
|
hDC = GetDC(hIndexWnd);
|
|
hDCDest = CreateCompatibleDC(hDC);
|
|
ReleaseDC(hIndexWnd, hDC);
|
|
}
|
|
else
|
|
{
|
|
hDCDest= CreateCompatibleDC(hDestDC);
|
|
}
|
|
if (!hDCDest)
|
|
goto MakeObjectCopyEnd;
|
|
|
|
/* Create a new monochrome BITMAP */
|
|
cxBitmap = (pCard->rcObject.right - pCard->rcObject.left);
|
|
cyBitmap = (pCard->rcObject.bottom - pCard->rcObject.top);
|
|
if( hDestDC == NULL )
|
|
{
|
|
hBitmap= CreateBitmap( cxBitmap, cyBitmap, 1, 1, NULL );
|
|
}
|
|
else
|
|
{
|
|
hBitmap= CreateCompatibleBitmap( hDestDC,cxBitmap, cyBitmap );
|
|
}
|
|
|
|
if( !hBitmap )
|
|
{
|
|
goto MakeObjectCopyEnd;
|
|
}
|
|
|
|
SetWindowOrgEx(hDCDest, 0, 0, (LPPOINT)NULL);
|
|
SetWindowExtEx(hDCDest, cxBitmap, cyBitmap, &sz);
|
|
|
|
/* Draw into the DC */
|
|
if (hObject = SelectObject(hDCDest, hBitmap))
|
|
{
|
|
/* Start by clearing the DC (white's enough 'cause it's monochrome) */
|
|
if (hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW)))
|
|
{
|
|
RECT rc;
|
|
|
|
rc = pCard->rcObject;
|
|
OffsetRect(&rc, -rc.left, -rc.top);
|
|
FillRect(hDCDest, &rc, hBrush);
|
|
DeleteObject(hBrush);
|
|
}
|
|
|
|
/* Draw the picture */
|
|
fError = !PicDraw(pCard, hDCDest, TRUE);
|
|
SelectObject(hDCDest, hObject); /* Needed? */
|
|
}
|
|
|
|
MakeObjectCopyEnd:
|
|
if (fError)
|
|
{
|
|
ErrorMessage(E_BITMAP_COPY_FAILED);
|
|
if (hBitmap)
|
|
{
|
|
DeleteObject(hBitmap);
|
|
hBitmap = NULL;
|
|
}
|
|
}
|
|
if (hDCDest)
|
|
DeleteDC(hDCDest);
|
|
|
|
Hourglass(FALSE);
|
|
return hBitmap;
|
|
}
|
|
|
|
NOEXPORT void NEAR SetFile (HANDLE fh)
|
|
{
|
|
lpStream->fh = fh;
|
|
vfbmp.bm.bmType = -1;
|
|
}
|
|
|
|
/******************* OLE STREAM Get, Put, ... routines **********************/
|
|
|
|
/*
|
|
* This Read is used to make Old Card bitmaps read like the BITMAP
|
|
* object in OLECLI.DLL. We must return:
|
|
*
|
|
* <type signature> 0x0700
|
|
* <type string> "BITMAP" (NULL terminated)
|
|
* BITMAP structure
|
|
* <BITMAP bits>
|
|
*
|
|
* So, I fill in "FAKEBITMAP" and read out of it until I'm through;
|
|
* then I just read the bitmap bits directly from the file.
|
|
*/
|
|
|
|
DWORD ReadOldStream(LPCARDSTREAM lpStream, LPBYTE lpbit, DWORD cb)
|
|
{
|
|
int xTmp, yTmp;
|
|
DWORD cRead = 0L;
|
|
short Temp ;
|
|
|
|
if (vfbmp.bm.bmType == -1)
|
|
{
|
|
iPos = 0;
|
|
vfbmp.ulVersion = 1L;
|
|
vfbmp.ulWhat = OT_STATIC;
|
|
vfbmp.cbName = 7L;
|
|
CopyMemory (vfbmp.szName, "BITMAP\0", 7);
|
|
vfbmp.res[0] = vfbmp.res[1] = vfbmp.res[2] = 0L;
|
|
vfbmp.bm.bmType = 0;
|
|
|
|
/* Read in the card dimensions */
|
|
MyByteReadFile(lpStream->fh, &vfbmp.bm.bmWidth, sizeof(vfbmp.bm.bmWidth));
|
|
MyByteReadFile(lpStream->fh, &vfbmp.bm.bmHeight, sizeof(vfbmp.bm.bmHeight));
|
|
|
|
vfbmp.bm.bmWidthBytes = ((vfbmp.bm.bmWidth + 0x000f) >> 4) << 1;
|
|
vfbmp.bm.bmPlanes = 1;
|
|
vfbmp.bm.bmBitsPixel = 1;
|
|
vfbmp.bm.bmBits = 0L;
|
|
|
|
/* Read in the card position */
|
|
MyByteReadFile(lpStream->fh, &Temp, sizeof(Temp));
|
|
xTmp = Temp ;
|
|
|
|
xTmp = (xTmp * CharFixWidth) / 8;
|
|
|
|
MyByteReadFile(lpStream->fh, &Temp, sizeof(Temp));
|
|
yTmp = Temp ;
|
|
|
|
yTmp = (yTmp * CharFixHeight) / 8;
|
|
|
|
/* We don't scale for compatibility's sake */
|
|
SetRect(&(CurCard.rcObject), xTmp, yTmp,
|
|
xTmp + vfbmp.bm.bmWidth - 1, yTmp + vfbmp.bm.bmHeight - 1);
|
|
vcLeft = (DWORD) sizeof(FAKEBITMAP);
|
|
vpfbmp = (BYTE *)&vfbmp;
|
|
}
|
|
#if 0
|
|
if (vcLeft)
|
|
{
|
|
cRead = min(vcLeft, cb);
|
|
for (i = 0; i < (int) cRead; i++)
|
|
*lpbit++ = *vpfbmp++;
|
|
vcLeft -= cRead;
|
|
cb -= cRead;
|
|
}
|
|
if (cb) {
|
|
/* Old bitmaps are always under 64K */
|
|
cRead += (DWORD) MyByteReadFile(lpStream->fh, lpbit + cRead, (int)cb);
|
|
vcbLeftToRead -= cRead;
|
|
}
|
|
|
|
return cRead;
|
|
#endif
|
|
|
|
switch (iPos)
|
|
{
|
|
case 0:
|
|
*(DWORD *)lpbit = vfbmp.ulVersion;
|
|
break;
|
|
|
|
case 1:
|
|
*(DWORD *)lpbit = vfbmp.ulWhat;
|
|
break;
|
|
|
|
case 2:
|
|
*(DWORD *)lpbit = vfbmp.cbName;
|
|
break;
|
|
|
|
case 3:
|
|
lstrcpy ((LPTSTR) lpbit, vfbmp.szName);
|
|
break;
|
|
|
|
case 4:
|
|
*(DWORD *)lpbit = vfbmp.res[0];
|
|
break;
|
|
|
|
case 5:
|
|
*(DWORD *)lpbit = vfbmp.res[1];
|
|
break;
|
|
|
|
case 6:
|
|
// This needs to return the amount of data
|
|
*(DWORD *)lpbit = vcbLeftToRead + sizeof(WIN16BITMAP);
|
|
break;
|
|
|
|
case 7:
|
|
// Should now be asking for the 16bit BITMAP Structure
|
|
// so copy it over
|
|
CopyMemory(lpbit, &vfbmp.bm, sizeof(WIN16BITMAP));
|
|
break;
|
|
|
|
case 8:
|
|
MyByteReadFile(lpStream->fh, lpbit, vcbLeftToRead);
|
|
vcbLeftToRead = 0;
|
|
break;
|
|
|
|
default:
|
|
#if DBG
|
|
MessageBox( NULL, TEXT("Should not have been called 10 times!"),
|
|
TEXT("ReadOldStream"), MB_OK );
|
|
#endif
|
|
cb = 0;
|
|
break;
|
|
};
|
|
iPos++;
|
|
|
|
return cb;
|
|
}
|
|
|
|
DWORD ReadStream(LPCARDSTREAM lpStream, LPBYTE lpbit, DWORD cb)
|
|
{
|
|
if (MyByteReadFile(lpStream->fh, lpbit, cb))
|
|
return (cb);
|
|
return (0);
|
|
}
|
|
|
|
DWORD WriteStream(LPCARDSTREAM lpStream, LPBYTE lpbit, DWORD cb)
|
|
{
|
|
if (MyByteWriteFile(lpStream->fh, lpbit, cb))
|
|
return (cb);
|
|
return (0);
|
|
}
|
|
|
|
HBITMAP MakeBitmapCopy(HBITMAP hbmSrc, PBITMAP pBitmap, HDC hDestDC )
|
|
{
|
|
HBITMAP hBitmap = NULL;
|
|
HDC hDCSrc = NULL;
|
|
HDC hDCDest = NULL;
|
|
HDC hDC;
|
|
BOOL fError = TRUE;
|
|
|
|
if( hDestDC == NULL )
|
|
{
|
|
hDC = GetDC(hIndexWnd);
|
|
hDCSrc = CreateCompatibleDC(hDC); /* get memory dc */
|
|
hDCDest = CreateCompatibleDC(hDC);
|
|
ReleaseDC(hIndexWnd, hDC);
|
|
}
|
|
else
|
|
{
|
|
hDCSrc = CreateCompatibleDC( hDestDC );
|
|
hDCDest = CreateCompatibleDC( hDestDC );
|
|
}
|
|
if (!hDCSrc || !hDCDest)
|
|
goto MakeCopyEnd;
|
|
|
|
/* select in passed bitmap */
|
|
if (!SelectObject(hDCSrc, hbmSrc))
|
|
goto MakeCopyEnd;
|
|
|
|
/* create new monochrome bitmap */
|
|
hBitmap= CreateBitmap( pBitmap->bmWidth, pBitmap->bmHeight, 1, GetDeviceCaps(hDCDest,NUMCOLORS), NULL );
|
|
if( !hBitmap )
|
|
{
|
|
goto MakeCopyEnd;
|
|
}
|
|
|
|
/* Now blt the bitmap contents. The screen driver in the source will
|
|
"do the right thing" in copying color to black-and-white. */
|
|
|
|
if( SelectObject(hDCDest, hBitmap) )
|
|
{
|
|
if( BitBlt(hDCDest, 0, 0, pBitmap->bmWidth, pBitmap->bmHeight, hDCSrc, 0, 0, SRCCOPY) )
|
|
{
|
|
fError= FALSE;
|
|
}
|
|
}
|
|
if( fError )
|
|
{
|
|
|
|
DeleteObject(hBitmap);
|
|
hBitmap = NULL;
|
|
goto MakeCopyEnd;
|
|
}
|
|
fError = FALSE;
|
|
|
|
MakeCopyEnd:
|
|
if (fError)
|
|
ErrorMessage(E_BITMAP_COPY_FAILED);
|
|
if (hDCSrc)
|
|
DeleteObject(hDCSrc);
|
|
if (hDCDest)
|
|
DeleteObject(hDCDest);
|
|
return hBitmap;
|
|
}
|
|
|
|
/* OleError() - Disposes of OLE errors.
|
|
*
|
|
* Note: This function (and ErrorMessage()) both use the window
|
|
* hwndError as parent when putting up dialogs.
|
|
*/
|
|
BOOL OleError(
|
|
OLESTATUS olestat)
|
|
{
|
|
switch (olestat) {
|
|
case OLE_WAIT_FOR_RELEASE:
|
|
cOleWait++;
|
|
|
|
case OLE_OK:
|
|
return FOLEERROR_OK;
|
|
|
|
case OLE_ERROR_STATIC: /* Only happens w/ dbl click */
|
|
ErrorMessage(W_STATIC_OBJECT);
|
|
break;
|
|
|
|
case OLE_ERROR_COMM:
|
|
ErrorMessage(E_FAILED_TO_LAUNCH_SERVER);
|
|
break;
|
|
|
|
case OLE_ERROR_REQUEST_NATIVE:
|
|
case OLE_ERROR_REQUEST_PICT:
|
|
case OLE_ERROR_ADVISE_NATIVE:
|
|
case OLE_ERROR_ADVISE_PICT:
|
|
case OLE_ERROR_OPEN: /* Invalid link? */
|
|
case OLE_ERROR_NAME:
|
|
if (CurCard.otObject == LINK)
|
|
{
|
|
if (hwndError == hIndexWnd)
|
|
{
|
|
if (DialogBox(hIndexInstance, (LPTSTR) MAKEINTRESOURCE(DTINVALIDLINK),
|
|
hwndError, (WNDPROC)lpfnInvalidLink) == IDD_LINK)
|
|
PostMessage(hIndexWnd, WM_COMMAND, LINKSDIALOG, 0L);
|
|
}
|
|
else
|
|
{
|
|
/* Failed, but already in LinksDlg!! */
|
|
ErrorMessage(E_FAILED_TO_UPDATE_LINK);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case OLE_BUSY:
|
|
ErrorMessage(E_SERVER_BUSY);
|
|
break;
|
|
|
|
default:
|
|
return FOLEERROR_NOTGIVEN;
|
|
}
|
|
return FOLEERROR_GIVEN;
|
|
}
|
|
|
|
BOOL GetNewLinkName(HWND hwndOwner, PCARD pCard)
|
|
{
|
|
BOOL fPath = FALSE;
|
|
BOOL fSuccess = FALSE;
|
|
BOOL fFile = FALSE;
|
|
DWORD dwSize = 0 ;
|
|
HANDLE hData;
|
|
HANDLE hData2 = NULL;
|
|
HANDLE hData3 = NULL;
|
|
HWND hwndOwnSave = NULL;
|
|
LPTSTR lpData2 = NULL;
|
|
LPTSTR lpstrData = NULL;
|
|
LPTSTR lpstrFile = NULL;
|
|
LPTSTR lpstrLink = NULL;
|
|
LPTSTR lpstrPath = NULL;
|
|
LPTSTR lpstrTemp = NULL;
|
|
OLECHAR*pOleData = NULL;
|
|
TCHAR szDocDefExt[10];
|
|
TCHAR szDocFile[PATHMAX];
|
|
TCHAR szDocPath[PATHMAX];
|
|
|
|
hwndOwnSave = OFN.hwndOwner;
|
|
|
|
if (OLE_OK != OleGetData(pCard->lpObject, vcfLink, &hData) ||
|
|
!(pOleData = GlobalLock(hData)))
|
|
goto Error;
|
|
|
|
lpstrData= Ole2Native( pOleData,3 ); // convert to native chars
|
|
|
|
lpstrTemp = lpstrData;
|
|
while (*lpstrTemp++)
|
|
continue;
|
|
lpstrPath = lpstrFile = lpstrTemp;
|
|
while (*(lpstrTemp = CharNext(lpstrTemp)))
|
|
if (*lpstrTemp == TEXT('\\'))
|
|
lpstrFile = lpstrTemp + 1;
|
|
|
|
lstrcpy(szDocFile, lpstrFile);
|
|
fPath = (*(lpstrFile - 1));
|
|
*(lpstrFile - 1) = TEXT('\0');
|
|
lstrcpy(szDocPath, ((lpstrPath != lpstrFile) ? lpstrPath : TEXT("")));
|
|
|
|
/* Fix bug: If we have <drive>:\<filename>, the starting directory
|
|
* should be <drive>:\, not just <drive>:.
|
|
*/
|
|
if (lstrlen(szDocPath) == 2)
|
|
lstrcat(szDocPath, TEXT("\\"));
|
|
|
|
if (fPath)
|
|
*(lpstrFile - 1) = TEXT('\\');
|
|
|
|
while (*lpstrFile != TEXT('.') && *lpstrFile)
|
|
lpstrFile++;
|
|
|
|
/* Make a filter that respects the link's class name */
|
|
OFN.nFilterIndex = MakeFilterSpec(lpstrData, lpstrFile, szServerFilter);
|
|
lstrcpy(szDocDefExt, (*lpstrFile) ? lpstrFile + 1 : TEXT(""));
|
|
OFN.lpstrDefExt = NULL;
|
|
OFN.lpstrCustomFilter = szCustFilterSpec;
|
|
OFN.lpstrFile = szDocFile;
|
|
OFN.lpstrTitle = szLinkCaption;
|
|
OFN.lpstrFilter = szServerFilter;
|
|
OFN.lpstrInitialDir = szDocPath;
|
|
OFN.hwndOwner = hwndOwner;
|
|
OFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
|
|
|
|
LockData(0);
|
|
fFile = GetOpenFileName(&OFN);
|
|
UnlockData(0);
|
|
if (fFile)
|
|
{
|
|
if (!(hData2 = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, ByteCountOf(PATHMAX * 2)))
|
|
|| !(lpstrLink = lpstrTemp = (LPTSTR) GlobalLock(hData2)))
|
|
goto Error;
|
|
|
|
/* If the user didn't specify an extension, use the default */
|
|
if (OFN.nFileExtension == lstrlen(szDocFile) && OFN.nFilterIndex)
|
|
{
|
|
LPTSTR lpstrFilter = szServerFilter;
|
|
|
|
while (*lpstrFilter && --OFN.nFilterIndex)
|
|
{
|
|
while (*lpstrFilter++) ;
|
|
while (*lpstrFilter++) ;
|
|
}
|
|
if (*lpstrFilter)
|
|
{
|
|
while (*lpstrFilter++) ;
|
|
lpstrFilter++;
|
|
lstrcat(szDocFile, lpstrFilter);
|
|
}
|
|
}
|
|
|
|
while (*lpstrTemp++ = *lpstrData++)
|
|
continue;
|
|
lstrcpy(lpstrTemp, szDocFile);
|
|
lpstrTemp += lstrlen(lpstrTemp) + 1;
|
|
lpstrData += lstrlen(lpstrData) + 1;
|
|
while (*lpstrTemp++ = *lpstrData++);
|
|
*lpstrTemp = (TCHAR) 0;
|
|
dwSize = (DWORD)(lpstrTemp - lpstrLink + 1);
|
|
|
|
// Convert to ascii. OLE1 doesn't do unicode
|
|
{
|
|
char buff[400];
|
|
INT oleSize;
|
|
oleSize= WideCharToMultiByte(
|
|
CP_ACP, 0,
|
|
lpstrLink, dwSize,
|
|
buff, sizeof(buff),
|
|
NULL, NULL );
|
|
CopyMemory( lpstrLink, buff, oleSize );
|
|
}
|
|
|
|
/* Unlock the appropriate memory blocks */
|
|
GlobalUnlock(hData); /* Unlock, because OleSetData() may free it */
|
|
GlobalUnlock(hData2);
|
|
GlobalFree( lpstrData );
|
|
lpstrData = NULL;
|
|
|
|
/* Compress the block to minimal size */
|
|
hData3 = GlobalReAlloc(hData2, ByteCountOf(lpstrTemp-lpstrLink+1), GMEM_MOVEABLE);
|
|
if (!hData3)
|
|
hData3 = hData2;
|
|
|
|
if (!OleError(OleSetData(pCard->lpObject, vcfLink, hData3)))
|
|
{
|
|
WaitForObject(pCard->lpObject);
|
|
fSuccess = (OleStatusCallBack == OLE_OK);
|
|
if (fSuccess)
|
|
{
|
|
fSuccess = !OleError(OleUpdate(pCard->lpObject));
|
|
if (fSuccess)
|
|
{
|
|
WaitForObject(pCard->lpObject);
|
|
if (OleStatusCallBack == OLE_OK)
|
|
{
|
|
CurCardHead.flags |= FDIRTY;
|
|
fSuccess = TRUE;
|
|
}
|
|
else
|
|
fSuccess = FALSE;
|
|
}
|
|
}
|
|
if (!fSuccess)
|
|
{
|
|
ErrorMessage(E_FAILED_TO_UPDATE);
|
|
goto Error;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(CommDlgExtendedError()) /* Assumes low memory. */
|
|
IndexOkError(EINSMEMORY);
|
|
|
|
Error:
|
|
if (!fSuccess) {
|
|
if (hData3)
|
|
GlobalFree(hData3);
|
|
|
|
if (pOleData)
|
|
GlobalUnlock(hData);
|
|
|
|
if( lpstrData )
|
|
LocalFree( lpstrData );
|
|
}
|
|
|
|
OFN.hwndOwner = hwndOwnSave;
|
|
return fSuccess;
|
|
}
|
|
|
|
void PicSaveUndo(PCARD pCard)
|
|
{
|
|
WORD fOleErrMsg;
|
|
|
|
/* If Undo object exists, delete it */
|
|
DeleteUndoObject();
|
|
|
|
/* Clone the current object */
|
|
if (pCard->lpObject)
|
|
{
|
|
if (fOleErrMsg = OleError(OleClone(pCard->lpObject, lpclient,
|
|
lhcdoc, szUndo, (LPOLEOBJECT FAR *)&lpObjectUndo)))
|
|
{
|
|
lpObjectUndo = NULL;
|
|
if (fOleErrMsg == FOLEERROR_NOTGIVEN)
|
|
ErrorMessage(W_FAILED_TO_CLONE_UNDO);
|
|
}
|
|
else
|
|
otObjectUndo = pCard->otObject;
|
|
}
|
|
}
|
|
|
|
void ErrorMessage(int id)
|
|
{
|
|
TCHAR buf[300];
|
|
|
|
LoadString(hIndexInstance, id, buf, CharSizeOf(buf));
|
|
MessageBox(hwndError, buf, szWarning, MB_OK | MB_ICONEXCLAMATION);
|
|
}
|
|
|
|
/* WaitForObject() - Waits, dispatching messages, until the object is free.
|
|
*
|
|
* If the object is busy, spin in a dispatch loop.
|
|
*/
|
|
void WaitForObject(LPOLEOBJECT lpObject)
|
|
{
|
|
if (lpObject)
|
|
{
|
|
while (OleQueryReleaseStatus(lpObject) == OLE_BUSY)
|
|
ProcessMessage(hIndexWnd, hAccel);
|
|
}
|
|
}
|
|
|
|
|
|
void Hourglass(BOOL fOn)
|
|
{
|
|
if (fOn)
|
|
{
|
|
if (!(cWait++))
|
|
hcurOle = SetCursor(hWaitCurs);
|
|
}
|
|
else
|
|
{
|
|
if (!(--cWait) && hcurOle)
|
|
{
|
|
SetCursor(hcurOle);
|
|
hcurOle = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void PicCreateFromFile(LPTSTR szPackageClass, LPTSTR szDropFile, BOOL fLink)
|
|
{
|
|
LPOLEOBJECT lpObject;
|
|
OBJECTTYPE otObject;
|
|
int fError;
|
|
#ifndef OLE_20
|
|
CHAR aszBuf1[PATHMAX];
|
|
CHAR aszBuf2[PATHMAX];
|
|
#endif
|
|
|
|
Hourglass(TRUE);
|
|
|
|
/* Don't replace the current object unless we're successful */
|
|
#ifndef OLE_20
|
|
wsprintfA (szObjectName, szObjFormat, idObjectMax + 1);
|
|
#else
|
|
wsprintfW (szObjectName, szObjFormat, idObjectMax + 1);
|
|
#endif
|
|
|
|
#ifndef OLE_20
|
|
WideCharToMultiByte (CP_ACP, 0, szPackageClass, -1, aszBuf1, PATHMAX, NULL, NULL);
|
|
WideCharToMultiByte (CP_ACP, 0, szDropFile, -1, aszBuf2, PATHMAX, NULL, NULL);
|
|
#endif
|
|
|
|
if (fLink)
|
|
{
|
|
#ifndef OLE_20
|
|
fError = OleCreateLinkFromFile(szPStdFile, lpclient, aszBuf1,
|
|
aszBuf2, NULL, lhcdoc, szObjectName,
|
|
&lpObject, olerender_draw, 0);
|
|
#else
|
|
fError = OleCreateLinkFromFile(szPStdFile, lpclient, szPackageClass,
|
|
szDropFile, NULL, lhcdoc, szObjectName,
|
|
&lpObject, olerender_draw, 0);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifndef OLE_20
|
|
fError = OleCreateLinkFromFile(szPStdFile, lpclient, aszBuf1,
|
|
aszBuf2, NULL, lhcdoc, szObjectName,
|
|
&lpObject, olerender_draw, 0);
|
|
#else
|
|
fError = OleCreateFromFile(szPStdFile, lpclient, szPackageClass,
|
|
szDropFile, lhcdoc, szObjectName,
|
|
&lpObject, olerender_draw, 0);
|
|
#endif
|
|
}
|
|
|
|
WaitForObject(lpObject);
|
|
if (fError != OLE_WAIT_FOR_RELEASE)
|
|
{
|
|
lpObject = NULL;
|
|
ErrorMessage(E_DRAG_DROP_FAILED);
|
|
} else {
|
|
LONG objType;
|
|
|
|
/* Figure out what kind of object we have */
|
|
OleQueryType(lpObject, &objType);
|
|
switch (objType) {
|
|
case OT_EMBEDDED: otObject = EMBEDDED; break;
|
|
case OT_LINK: otObject = LINK; break;
|
|
default: otObject = STATIC; break;
|
|
}
|
|
DoSetHostNames(lpObject, otObject);
|
|
}
|
|
|
|
if (lpObject)
|
|
{
|
|
if (CurCard.lpObject)
|
|
PicDelete(&CurCard);
|
|
CurCard.lpObject = lpObject;
|
|
CurCard.otObject = otObject;
|
|
CurCard.idObject = idObjectMax++;
|
|
InvalidateRect(hEditWnd, NULL, TRUE);
|
|
SetRect(&(CurCard.rcObject), 0, 0, 0, 0);
|
|
CurCardHead.flags |= FDIRTY;
|
|
#if 0
|
|
fCreateFromFile = TRUE;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
BOOL EditingEmbObject(
|
|
PCARD pCard)
|
|
{
|
|
if (pCard->lpObject && pCard->otObject == EMBEDDED &&
|
|
OleQueryOpen(pCard->lpObject) == OLE_OK) /* embedded object open for editing */
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
int UpdateEmbObject(
|
|
PCARD pCard,
|
|
int Flags)
|
|
{
|
|
int Result = IDYES;
|
|
TCHAR szMsg[100];
|
|
|
|
/* If an embedded object is open for editing, try to update */
|
|
if (EditingEmbObject(&CurCard))
|
|
{
|
|
LoadString(hIndexInstance, IDS_UPDATEEMBOBJECT, szMsg, CharSizeOf(szMsg));
|
|
Result = MessageBox(hIndexWnd, szMsg, szCardfile, Flags);
|
|
if (Result == IDYES)
|
|
{
|
|
switch (OleError(OleUpdate(CurCard.lpObject)))
|
|
{
|
|
case FOLEERROR_NOTGIVEN:
|
|
ErrorMessage(E_FAILED_TO_UPDATE);
|
|
break;
|
|
#if 0
|
|
case FOLEERROR_GIVEN:
|
|
break;
|
|
#endif
|
|
case FOLEERROR_OK:
|
|
WaitForObject(CurCard.lpObject);
|
|
CurCardHead.flags |= FDIRTY;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
BOOL InsertObjectInProgress(
|
|
void)
|
|
{
|
|
TCHAR szMsg[200];
|
|
|
|
if (EditingEmbObject(&CurCard) && !fInsertComplete)
|
|
{
|
|
LoadString(hIndexInstance, IDS_RETRYAFTERINSERT, szMsg, CharSizeOf(szMsg));
|
|
MessageBox(hIndexWnd, szMsg, szCardfile, MB_OK);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void DoSetHostNames(
|
|
LPOLEOBJECT lpObject,
|
|
OBJECTTYPE otObject)
|
|
{
|
|
if (lpObject && otObject == EMBEDDED)
|
|
{
|
|
#ifndef OLE_20
|
|
CHAR aszCardfile[60];
|
|
CHAR aszBuf[PATHMAX];
|
|
|
|
WideCharToMultiByte (CP_ACP, 0, szCardfile, -1, aszCardfile, 60, NULL, NULL);
|
|
WideCharToMultiByte (CP_ACP, 0, (*CurIFile) ? CurIFile : szUntitled, -1,
|
|
aszBuf, PATHMAX, NULL, NULL);
|
|
#endif
|
|
|
|
WaitForObject(lpObject);
|
|
#ifndef OLE_20
|
|
OleError(OleSetHostNames(lpObject, aszCardfile, aszBuf));
|
|
#else
|
|
OleError(OleSetHostNames(lpObject, szCardfile,
|
|
(*CurIFile) ? CurIFile : szUntitled));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* delete undo object if any */
|
|
void DeleteUndoObject(
|
|
void)
|
|
{
|
|
if (!lpObjectUndo)
|
|
return;
|
|
WaitForObject(lpObjectUndo);
|
|
if (lpObjectUndo && OleError(OleDelete(lpObjectUndo))) {
|
|
ErrorMessage(E_FAILED_TO_DELETE_OBJECT);
|
|
}
|
|
lpObjectUndo = NULL;
|
|
}
|
|
|