windows-nt/Source/XPSP1/NT/shell/osshell/accesory/clipbrd/clipfile.c
2020-09-26 16:20:57 +08:00

966 lines
30 KiB
C

/*
* CLIPFILE.C - Windows Clipboard File I/O Routines
*
* Copyright 1985-92, Microsoft Corporation
*/
/* NOTE:
* When saving the contents of the clipboard we SetClipboardData(fmt, NULL)
* to free up the memory associated with each clipboard format. Then
* after we are done saving we take over as the clipboard owner. This
* causes OWNERDRAW formats to be lost in the save process.
*/
/*
*
* Touched by : Anas Jarrah
* On Date : May 11/1992.
* Revision remarks by Anas Jarrah ext #15201
* This file has been changed to comply with the Unicode standard
* Following is a quick overview of what I have done.
*
* Was Changed it into Remark
* === =============== ======
* CHAR TCHAR if it refers to a text elements
* LPCHAR & LPSTR LPTSTR if it refers to text.
* LPCHAR & LPSTR LPBYTE if it does not refer to text
* "..." TEXT("...") compile time macro resolves it.
* '...' TEXT('...') same
* strlen CharStrLen compile time macro resolves it.
* strcpy CharStrCpy compile time macro resolves it.
* strcmp CharStrCmp compile time macro resolves it.
* strcat CharStrCat compile time macro resolves it.
* LoadResource LoadResource(A/W) NT compiles resource strings into
* Unicode binaries
* MOpenFile() MapOpenFile/MOpenFile Depending on whether Unicode is defined or not.
* This is a temporary cluge, That has to be taken care of.
*
*
*/
#include "clipbrd.h"
#include "dib.h"
#define ATTRDIRLIST 0xC010
// Windows 3.1 programs were packed on byte boundaries.
#pragma pack(1)
// Windows 3.1 BITMAP struct - used to save Win 3.1 .CLP files
typedef struct {
WORD bmType;
WORD bmWidth;
WORD bmHeight;
WORD bmWidthBytes;
BYTE bmPlanes;
BYTE bmBitsPixel;
LPVOID bmBits;
} WIN31BITMAP;
#pragma pack()
/* EXTERN data */
extern BOOL fAnythingToRender;
/* FORWARD procs */
HBITMAP PASCAL BitmapToBitmap(HBITMAP, WORD, WORD);
TCHAR szFileSpecifier[] = TEXT("*.CLP");
TCHAR szFileName[MAX_PATH];
BOOL fNTReadFileFormat;
#ifdef JAPAN
extern TCHAR szCaptionName[];
#endif
/* ofSaveStruct is required; Otherwise, the following bug will occur
* When the contents of the clipboard are loaded from a file, the
* ofStruct is used to open the file and the data handles assigned to
* the clipboard are NULL because of DELAYED RENDERING; Delayed
* rendering will be done by reading from the file (ofStruct). But,
* now, if the contents are to be saved into another file, it should
* use the same ofStruct, because data has to be obtained from this
* file using delayed rendering; So, a temporary ofSaveStruct is used
* to hold the saved file's info; Once the save is successful, the
* contents of ofSaveStruct are copied onto ofStruct
*/
/* the ofStruct and ofSaveStruct are replaced by szFileName and
* szSaveFileName strings.
*/
TCHAR szSaveFileName[MAX_PATH];
BOOL fNTSaveFileFormat;
/*
* IsWriteable()
*
* Test if a clipboard format is writeable(i.e. if it makes sense to write it)
* OWNERDRAW and others can't be written because we (CLIPBRD) will become the
* owner when the files are reopened.
*/
BOOL NEAR PASCAL IsWriteable(UINT Format)
{
/* Are the PRIVATEFIRST and PRIVATELAST things right? */
if ((Format >= CF_PRIVATEFIRST && Format <= CF_PRIVATELAST) || Format == CF_OWNERDISPLAY)
return(FALSE);
if (!fNTSaveFileFormat &&
(Format == CF_UNICODETEXT || Format == CF_ENHMETAFILE || Format == CF_DSPENHMETAFILE))
return(FALSE);
return(TRUE);
}
/*
* ReadClipboardFromFile()
*
* Read in a clipboard file and register all the formats in delayed mode.
* to render things for real reopen the file specified by szFileName (was ofStruct).
*
* NOTE:
* This makes us the clipboard owner.
*
* Bug 14564: Changed return value to a short integer noting why the
* reading failed.
* Return Value: 0 Success
* 1 Improper format
* 2 OpenClipboard failed
*/
#define READFILE_SUCCESS 0
#define READFILE_IMPROPERFORMAT 1
#define READFILE_OPENCLIPBRDFAIL 2
short NEAR PASCAL ReadClipboardFromFile(HWND hwnd,INT fh)
{
register WORD i;
FILEHEADER FileHeader;
FORMATHEADER FormatHeader;
/* Read the File Header */
_lread(fh, (LPBYTE)&FileHeader, sizeof(FILEHEADER));
/* Sanity check, make sure this is one of ours. */
#ifndef JAPAN
if (FileHeader.magic == CLP_NT_ID)
fNTReadFileFormat = TRUE;
else if (FileHeader.magic == CLP_ID)
fNTReadFileFormat = FALSE;
else
return(READFILE_IMPROPERFORMAT);
if (FileHeader.FormatCount > 100)
return(READFILE_IMPROPERFORMAT);
#else
if (FileHeader.magic == CLP_NT_ID)
fNTReadFileFormat = TRUE;
else if (FileHeader.magic == CLP_ID)
fNTReadFileFormat = FALSE;
else
goto improperformat;
if (FileHeader.FormatCount > 100)
{
improperformat:
TCHAR szOutMessage[BUFFERLEN];
TCHAR szCapBuffer[SMALLBUFFERLEN];
LoadStringW(hInst, IDS_NAME, szCapBuffer, SMALLBUFFERLEN);
LoadStringW(hInst, IDS_ENOTVALIDFILE, szOutMessage, BUFFERLEN);
MessageBox(hwnd, szOutMessage,szCapBuffer, MB_OK | MB_ICONEXCLAMATION);
return(READFILE_IMPROPERFORMAT);
}
#endif
/* We become the clipboard owner here! */
if (!OpenClipboard(hwnd))
return(READFILE_OPENCLIPBRDFAIL);
EmptyClipboard();
for (i=0; i < FileHeader.FormatCount; i++)
{
if (fNTReadFileFormat)
_lread(fh, (LPBYTE)&(FormatHeader.FormatID), sizeof(FormatHeader.FormatID));
else {
FormatHeader.FormatID = 0; /* initialize the high WORD */
_lread(fh, (LPBYTE)&(FormatHeader.FormatID), sizeof(WORD));
}
_lread(fh, (LPBYTE)&(FormatHeader.DataLen), sizeof(FormatHeader.DataLen));
_lread(fh, (LPBYTE)&(FormatHeader.DataOffset), sizeof(FormatHeader.DataOffset));
_lread(fh, (LPBYTE)&(FormatHeader.Name), sizeof(FormatHeader.Name));
if (PRIVATE_FORMAT(FormatHeader.FormatID))
FormatHeader.FormatID = (UINT)RegisterClipboardFormat(FormatHeader.Name);
/* Delayed Render. */
SetClipboardData(FormatHeader.FormatID, NULL);
}
/* Now, clipbrd viewer has something to render */
if (FileHeader.FormatCount > 0)
fAnythingToRender = TRUE;
CloseClipboard();
return(READFILE_SUCCESS);
}
/*
* OpenClipboardFile()
*/
void NEAR PASCAL OpenClipboardFile(HWND hwnd)
{
INT fh;
lstrcpy(szFileName, TEXT(""));
OFN.lpstrTitle = szOpenCaption;
OFN.lpstrFile = szFileName;
/* Added OFN_FILEMUSTEXIST. 4 March 1991 clarkc */
/* Added OFN_HIDEREADONLY. Happy now, Patrick? :) 1 Oct 1992 a-mgates.*/
OFN.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
/* All long pointers should be defined immediately before the call.
* L.Raman - 2/12/91
*/
OFN.lpstrDefExt = (LPTSTR)szDefExt;
OFN.lpstrFilter = (LPTSTR)szFilterSpec;
OFN.lpstrCustomFilter = (LPTSTR)szCustFilterSpec;
fh = GetOpenFileName ((LPOPENFILENAME) &OFN);
if (fh)
{
fh = (INT)CreateFile((LPCTSTR)szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh > 0)
{
short nReadError;
if (ClearClipboard(hwnd))
{
if (nReadError = ReadClipboardFromFile(hwnd, fh))
{
TCHAR szErr[MSGMAX];
LoadString (hInst, IDS_READERR + nReadError, szErr, MSGMAX);
MessageBox(hwnd,szErr,szAppName,MB_OK | MB_ICONEXCLAMATION);
}
}
_lclose(fh);
}
}
/* On GetOpenFileName failure CommDlgExtendedError will return a value.*/
if(CommDlgExtendedError())
{
MemErrorMessage();
}
}
/*
* WriteFormatBlock() -
*/
DWORD NEAR PASCAL WriteFormatBlock(INT fh,DWORD offset,DWORD DataOffset,
DWORD DataLen,UINT Format,LPSTR szName)
{
FORMATHEADER FormatHeader;
DWORD dwBytesWritten = 0;
FormatHeader.FormatID = Format;
FormatHeader.DataLen = DataLen;
FormatHeader.DataOffset = DataOffset;
lstrcpy(FormatHeader.Name, szName);
_llseek(fh, offset, 0);
if (fNTSaveFileFormat)
dwBytesWritten += _lwrite(fh, (LPSTR)&(FormatHeader.FormatID), sizeof(FormatHeader.FormatID));
else
dwBytesWritten += _lwrite(fh, (LPSTR)&(FormatHeader.FormatID), sizeof(WORD));
dwBytesWritten += _lwrite(fh, (LPSTR)&(FormatHeader.DataLen), sizeof(FormatHeader.DataLen));
dwBytesWritten += _lwrite(fh, (LPSTR)&(FormatHeader.DataOffset), sizeof(FormatHeader.DataOffset));
dwBytesWritten += _lwrite(fh, (LPSTR)&(FormatHeader.Name), sizeof(FormatHeader.Name));
return(dwBytesWritten);
}
/*
* lread() - Good ol' _lread that will handle >64k
*/
#define MAXREAD ((LONG) (60L * 1024L))
DWORD APIENTRY lread(INT hFile,void FAR *pBuffer,DWORD dwBytes)
{
DWORD dwByteCount = dwBytes;
#ifdef WIN16
BYTE huge *hpBuffer = pBuffer;
while (dwByteCount > MAXREAD)
{
if (_lread(hFile, hpBuffer, (WORD)MAXREAD) != MAXREAD)
return(0);
dwByteCount -= MAXREAD;
hpBuffer += MAXREAD;
}
#else
BYTE FAR *hpBuffer = pBuffer;
#endif
if ((DWORD)_lread(hFile, hpBuffer, dwByteCount) != dwByteCount)
return(0);
return(dwBytes);
}
/*
* lwrite() - Good ol' _lwrite that will handle >64k
*/
DWORD APIENTRY lwrite(INT hFile,void FAR *pBuffer,DWORD dwBytes)
{
DWORD dwByteCount=dwBytes;
#ifdef WIN16
BYTE huge *hpBuffer = pBuffer;
while (dwByteCount > MAXREAD)
{
if (_lwrite(hFile, (LPSTR)hpBuffer, (WORD)MAXREAD) != MAXREAD)
return(0);
dwByteCount -= MAXREAD;
hpBuffer += MAXREAD;
}
#else
BYTE FAR *hpBuffer = pBuffer;
#endif
if ((DWORD)_lwrite(hFile, (LPSTR)hpBuffer, dwByteCount) != dwByteCount)
return(0);
return(dwBytes);
}
/*
* WriteDataBlock() -
*
* Returns:
* # of bytes written to the output file
*
* NOTE: Write saves the name of a temp file in the clipboard for it's
* own internal clipboard format. This file goes aways when Write
* (or windows?) shuts down. Thus saving Write clipboards won't work
* (should we special case hack this?)
*
*/
DWORD NEAR PASCAL WriteDataBlock(register INT hFile,LONG offset,UINT Format)
{
WORD wPalEntries;
LPBYTE lpData;
DWORD dwSize;
BITMAP bitmap;
HANDLE hMF;
HANDLE hBitmap;
HANDLE hLogPalette;
register HANDLE hData;
LPLOGPALETTE lpLogPalette;
LPMETAFILEPICT lpMFP;
HENHMETAFILE hEMF;
WIN31BITMAP bmWin31;
if (!(hData = GetClipboardData(Format)))
return(0);
if(_llseek(hFile, offset, 0) != (int)offset)
return(0);
/* We have to special case a few common formats but most things
* get handled in the default case.
*/
switch (Format)
{
case CF_ENHMETAFILE:
hEMF = hData;
dwSize = (DWORD) GetEnhMetaFileBits(hEMF, 0, NULL); /* Get data size */
if (!(hData = GlobalAlloc(GHND, dwSize))) /* allocate mem for EMF bits */
return(0);
if (!(lpData = GlobalLock(hData)))
return(0);
if (!GetEnhMetaFileBits(hEMF, dwSize, (LPBYTE)lpData))
return(0);
dwSize = lwrite(hFile, lpData, dwSize);
GlobalUnlock(hData);
GlobalFree(hData);
break;
case CF_METAFILEPICT:
if (!(lpMFP = (LPMETAFILEPICT)GlobalLock(hData))) /* get header */
return(0);
if (fNTSaveFileFormat)
_lwrite(hFile, (LPBYTE)lpMFP, sizeof(METAFILEPICT)); /* write header */
else {
/* If we save the metafile in the Windows 3.1 .CLP file format
we have to save the METAFILEPICT structure as a 16bit METAFILEPICT
structure. This may cause loss of information if the
hight half of the METAFILEPICT structure's fields are used.
[pierrej 5/27/92] */
_lwrite(hFile, (LPBYTE)&(lpMFP->mm), sizeof(WORD));
_lwrite(hFile, (LPBYTE)&(lpMFP->xExt), sizeof(WORD));
_lwrite(hFile, (LPBYTE)&(lpMFP->yExt), sizeof(WORD));
_lwrite(hFile, (LPBYTE)&(lpMFP->hMF), sizeof(WORD));
}
hMF = lpMFP->hMF;
GlobalUnlock(hData); /* unlock the header */
/* A-MGates 9/15/92 - Converted this block to use */
/* GetMetaFileBitsEx */
/* Figure out how big a block we need */
dwSize = GetMetaFileBitsEx(hMF, 0, NULL);
if (0 == dwSize)
{
return(0);
}
hData = GlobalAlloc(GMEM_MOVEABLE, dwSize);
if (!(lpData = GlobalLock(hData)))
{
return(0);
}
if (dwSize != GetMetaFileBitsEx(hMF, dwSize, lpData))
{
GlobalUnlock(hData);
GlobalFree(hData);
return(0);
}
dwSize = lwrite(hFile, lpData, dwSize); /* spit them out */
GlobalUnlock(hData);
GlobalFree(hData);
if(dwSize)
if (fNTSaveFileFormat)
dwSize += sizeof(METAFILEPICT); /* we wrote this much data */
else
dwSize += SIZE_OF_WIN31_METAFILEPICT_STRUCT;
break;
case CF_BITMAP:
// hBitmap = hData;
/* Writing DDBs to disk is bad. Therefore, we */
/* write an intelligent CF_DIB block instead. */
/* A-MGATES 9/29/92 */
Format = CF_DIB;
hBitmap = DibFromBitmap((HBITMAP)hData, BI_RGB, 4, NULL);
lpData = GlobalLock(hBitmap);
// dwSize might be too big, but we can live with that.
dwSize = GlobalSize(lpData);
_lwrite(hFile, lpData, dwSize);
GlobalUnlock(hBitmap);
GlobalFree(hBitmap);
break;
#ifdef ICKYOLDCODE
if (!fNTSaveFileFormat)
hBitmap = BitmapToBitmap(hBitmap, 4, 1);
GetObject(hBitmap, sizeof(BITMAP), (LPBYTE) &bitmap);
dwSize = (DWORD)bitmap.bmWidthBytes * bitmap.bmHeight * bitmap.bmPlanes;
if (!fNTSaveFileFormat)
{
// Round up to the nearest TWO bytes when saving to Win 3.1,
// not the nearest four, which is what GetObject gives you.
// Note: The WidthBytes calculation does not include
// bmPlanes in the multiplication because it seems to represent
// bytes in a given plane.
bitmap.bmWidthBytes =
((bitmap.bmWidth * bitmap.bmBitsPixel)+ 15 ) >> 3;
// ">> 3" == " / 8", except cheaper.
if (bitmap.bmWidthBytes & 1)
{
bitmap.bmWidthBytes++;
}
}
if (!(hData = GlobalAlloc(GHND, dwSize)))
return(0);
if (!(lpData = GlobalLock(hData)))
{
GlobalFree(hData);
return(0);
}
GetBitmapBits(hBitmap, dwSize, lpData);
if (fNTSaveFileFormat)
_lwrite(hFile, (LPBYTE) & bitmap, sizeof(BITMAP));
else {
/* If we save the bitmap in the Windows 3.1 .CLP file format
we have to save the BITMAP structure as a 16bit BITMAP
structure. This may cause loss of information if the
hight half of the BITMAP structure's fields are used.
[pierrej 5/27/92] */
bmWin31.bmType = bitmap.bmType;
bmWin31.bmWidth = bitmap.bmWidth;
bmWin31.bmHeight = bitmap.bmHeight;
bmWin31.bmWidthBytes = bitmap.bmWidthBytes;
bmWin31.bmPlanes = bitmap.bmPlanes;
bmWin31.bmBitsPixel = bitmap.bmBitsPixel;
bmWin31.bmBits = bitmap.bmBits;
_lwrite(hFile, (LPBYTE) &bmWin31, sizeof(WIN31BITMAP));
}
dwSize = lwrite(hFile, lpData, dwSize);
GlobalUnlock(hData);
GlobalFree(hData);
if(dwSize)
if (fNTSaveFileFormat)
dwSize += sizeof(BITMAP);
else
dwSize += sizeof(WIN31BITMAP);
break;
#endif
case CF_PALETTE:
/* Get the number of palette entries */
GetObject(hData, sizeof(WORD), (LPBYTE)&wPalEntries);
/* Allocate enough place to build the LOGPALETTE struct */
dwSize = (DWORD)(sizeof(LOGPALETTE) + (LONG)wPalEntries * sizeof(PALETTEENTRY));
if (!(hLogPalette = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, dwSize)))
{
dwSize = 0L;
goto Palette_Error;
}
if (!(lpLogPalette = (LPLOGPALETTE)GlobalLock(hLogPalette)))
{
dwSize = 0L;
goto Palette_Error;
}
lpLogPalette->palVersion = 0x300; /* Windows 3.00 */
lpLogPalette->palNumEntries = wPalEntries;
if (GetPaletteEntries(hData, 0, wPalEntries,
(LPPALETTEENTRY)(lpLogPalette->palPalEntry)) == 0)
{
dwSize = 0L;
goto Palette_Error;
}
/* Write the LOGPALETTE structure onto disk */
dwSize = lwrite(hFile, (LPBYTE)lpLogPalette, dwSize);
Palette_Error:
if (lpLogPalette)
GlobalUnlock(hLogPalette);
if (hLogPalette)
GlobalFree(hLogPalette);
break;
default:
dwSize = GlobalSize(hData);
if (0 ==(lpData = GlobalLock(hData)) )
{
return 0;
}
dwSize = _lwrite(hFile, lpData, dwSize);
GlobalUnlock(hData);
break;
}
/* Return the number of bytes written. */
return(dwSize);
}
/* This function will return the number of clipboard formats compatible with
the Windows 3.1 clipboard, this excludes CF_UNICODETEXT, CF_ENHMETAFILE and
CF_DSPENHMETAFILE
*/
int Count16BitClipboardFormats(void)
{
int iCount;
iCount = CountClipboardFormats();
if (IsClipboardFormatAvailable(CF_UNICODETEXT))
iCount--;
if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
iCount--;
if (IsClipboardFormatAvailable(CF_DSPENHMETAFILE))
iCount--;
return iCount;
}
/*
* SaveClipboardData() - Writes a clipboard file.
*
* In:
* hwnd handle of wnd that becomes the clipboard owner
* szFileName file handle to read from
*
* NOTE:
* When done we call ReadClipboardFromFile(). this makes us the
* clipboard owner.
*/
BOOL NEAR PASCAL SaveClipboardData(HWND hwnd,LPTSTR szLocalFileName)
{
INT fh;
register UINT Format;
DWORD HeaderPos;
DWORD DataPos;
DWORD datasize;
BOOL fComplain;
BOOL fDIBUsed;
HCURSOR hCursor;
FILEHEADER FileHeader;
TCHAR szComplaint[BUFFERLEN];
TCHAR szName[CCHFMTNAMEMAX];
WORD wHeaderSize;
UINT uiSizeHeaderToWrite;
/* First open the clipboard */
if (!OpenClipboard(hwndMain))
return(FALSE);
/* Open the file */
fh = (INT)CreateFile((LPCTSTR)szLocalFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == -1)
{
GetLastError();
CloseClipboard();
return(FALSE);
}
/* Fill out the file header structure */
if (fNTSaveFileFormat) {
FileHeader.magic = CLP_NT_ID; /* magic number to tag our files */
uiSizeHeaderToWrite = (sizeof(UINT) + 2*sizeof(DWORD) + CCHFMTNAMEMAX*sizeof(TCHAR));
} else {
FileHeader.magic = CLP_ID; /* magic number to tag our files */
uiSizeHeaderToWrite = (sizeof(WORD) + 2*sizeof(DWORD) + CCHFMTNAMEMAX*sizeof(TCHAR));
}
FileHeader.FormatCount = 0; /* dummy for now */
/* Update HeaderPos and DataPos */
HeaderPos = sizeof(FILEHEADER);
/* This is the maximum number of formats that will be written. Potentially
* some may fail and some space will be wasted.
* In 32bit the number of bytes written to the disk isn't sizeof(FORMATHEADER)
* because of DWORD alignment in the FORMATHEADER structure. Instead we write
* the format headre structure one field at a time to remain compatible with
* the 16bit Windows versions.
*/
if (fNTSaveFileFormat)
DataPos = HeaderPos + (uiSizeHeaderToWrite * CountClipboardFormats());
else
DataPos = HeaderPos + (uiSizeHeaderToWrite * Count16BitClipboardFormats());
/* Now loop throught the data, one format at a time, and write out the data. */
fComplain = FALSE;
LoadString(hInst, IDS_FMTNOTSAV, szComplaint, BUFFERLEN);
hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE);
/* Enumerate all formats */
Format = 0;
fDIBUsed = FALSE;
while ((Format = EnumClipboardFormats(Format)) != 0)
{
if (IsWriteable(Format))
{
// DO NOT write CF_BITMAP to disk. Transform to CF_DIB
// and write that instead.
if (CF_BITMAP == Format || CF_DIB == Format)
{
if (!fDIBUsed)
{
fDIBUsed = TRUE;
}
// If I've already done DIB, go on to the next format.
else continue;
}
GetClipboardName((Format == CF_BITMAP ? CF_DIB : Format),
szName, sizeof(szName));
if ((datasize = WriteDataBlock(fh, DataPos, Format)) != 0)
{
/* Create a Format header and write it to the file */
wHeaderSize = (WORD)WriteFormatBlock(fh,
HeaderPos, DataPos, datasize,
(Format == CF_BITMAP ? CF_DIB : Format),
(LPTSTR)szName);
if(wHeaderSize < uiSizeHeaderToWrite)
{
fComplain = TRUE;
break;
}
HeaderPos += wHeaderSize;
/* Update the data pos for the next block */
DataPos += datasize;
FileHeader.FormatCount++; /* this format has been written */
}
else
{
fComplain = TRUE;
break;
}
}
}
ShowCursor(FALSE);
SetCursor(hCursor);
if (fComplain)
{
#ifdef JAPAN
/* Use Japanese message for caption instead of app name */
MessageBox(hwnd, szComplaint, szCaptionName, MB_OK | MB_ICONEXCLAMATION);
#else
MessageBox(hwnd, szComplaint, szAppName, MB_OK | MB_ICONEXCLAMATION);
#endif
CloseClipboard();
_lclose(fh);
return(FALSE);
}
CloseClipboard(); /* we are done looking at this */
_llseek(fh, 0L, 0); /* move back to the start of file */
/* Write the File Header with the correct number of formats written */
_lwrite(fh, (LPBYTE) & FileHeader, sizeof(FILEHEADER));
/* Now we open the clipboard and become the owner. this places
* all the things we just saved in the clipboard (and throws out
* those things we didn't save)
*/
_llseek(fh, 0L, 0);
/* ofStruct will be used for reopening the file */
lstrcpy(szFileName, szSaveFileName);
fNTReadFileFormat = fNTSaveFileFormat;
ReadClipboardFromFile(hwndMain, fh);
_lclose(fh);
return(TRUE);
}
/*
* SaveClipboardToFile() -
*/
void NEAR PASCAL SaveClipboardToFile(HWND hwnd)
{
INT hFile;
OFN.lpstrTitle = szSaveCaption;
OFN.lpstrFile = szSaveFileName;
szSaveFileName[0] = 0;
OFN.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST |
OFN_OVERWRITEPROMPT | OFN_NOREADONLYRETURN;
/* All long pointers should be defined immediately before the call. */
OFN.lpstrDefExt = (LPTSTR)szDefExt;
OFN.lpstrFilter = (LPTSTR)szFilterSpec;
OFN.lpstrCustomFilter = NULL;
OFN.lpfnHook = NULL;
OFN.nFilterIndex = 1;
hFile = GetSaveFileName ((LPOPENFILENAME) &OFN);
if (hFile)
{
// The first filter listed is "NT Clipboard File". The second is
// "Windows 3.1 Clipboard file".
fNTSaveFileFormat = (1 == OFN.nFilterIndex);
hFile = (INT)CreateFile((LPCTSTR)szSaveFileName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != -1)
/* The file already exists and the user wants to
* overwrite! Now, we have to check whether this
* file is the most recently saved clip file;
* If so, it will be used for delayed rendering; So,
* before we overwrite this file we must read all data
* from it thro RENDERALLFORMATS;
* Fix for Bug #5602 --SANKAR-- 10-16-89
*/
{
CloseHandle((HANDLE)hFile);
if (lstrcmp(szSaveFileName, szFileName) == 0)
{
SendMessage(hwndMain, WM_RENDERALLFORMATS, 0, 0L);
}
}
if (!SaveClipboardData(hwnd, (LPTSTR)szSaveFileName))
{
/* If Failure, Delete the incomplete file */
DeleteFile(szSaveFileName);
}
}
}
//
// Purpose:
// Convert an existing bitmap to the given number of planes and
// bits/pixel.
//
// Parameters:
// hBitmap - Handle to the existing bitmap.
// wPlanes - Number of planes in the destination bitmap.
// wBitCount - Number of bits/pel in the destination bitmap.
//
// Returns:
// A handle to the converted bitmap.
//
////////////////////////////////////////////////////////////////////////////
HBITMAP PASCAL BitmapToBitmap(HBITMAP hBitmap, WORD wPlanes, WORD wBitCount)
{
BITMAP bm;
BITMAPINFOHEADER BmpInfoHeader;
HANDLE hDib, hBmp;
LPBYTE lpDib, lpBits;
DWORD dwLength, dwSize;
int iColorTable;
int iColorUsed;
HDC hDC;
/*
** Get the size of the bitmap. These values are used to setup the memory
** requirements for the DIB.
*/
GetObject(hBitmap,sizeof(BITMAP),(LPSTR)&bm);
if ((bm.bmBitsPixel == wBitCount) && (bm.bmPlanes == wPlanes))
return hBitmap;
#if 0
dwSize = dwLength = (DWORD)(bm.bmWidthBytes+sizeof(WORD)) * bm.bmHeight * bm.bmPlanes;
#else
dwSize = dwLength = (DWORD)(((bm.bmWidth * wBitCount + 7)/8)*2 + 1)/2
* wPlanes * bm.bmHeight;
#endif
switch(bm.bmBitsPixel * bm.bmPlanes)
{
case 1:
iColorTable = sizeof(RGBQUAD) * 2;
break;
case 4:
iColorTable = sizeof(RGBQUAD) * 16;
break;
case 8:
iColorTable = sizeof(RGBQUAD) * 256;
break;
case 24:
default:
iColorTable = 0;
break;
}
iColorUsed = iColorTable / sizeof(RGBQUAD);
dwLength += (sizeof(BITMAPINFOHEADER) + iColorTable);
/*
** Create the DIB. First, to the size of the bitmap. We will calculate
** the new memory requirements if DIB-Compression is desired.
*/
if(hDib = GlobalAlloc(GHND,dwLength)) {
if(lpDib = GlobalLock(hDib))
{
((LPBITMAPINFOHEADER)lpDib)->biSize = sizeof(BITMAPINFOHEADER);
((LPBITMAPINFOHEADER)lpDib)->biWidth = bm.bmWidth;
((LPBITMAPINFOHEADER)lpDib)->biHeight = bm.bmHeight;
((LPBITMAPINFOHEADER)lpDib)->biPlanes = 1;
((LPBITMAPINFOHEADER)lpDib)->biBitCount = bm.bmBitsPixel*bm.bmPlanes;
((LPBITMAPINFOHEADER)lpDib)->biCompression = BI_RGB;
((LPBITMAPINFOHEADER)lpDib)->biSizeImage = 0;
((LPBITMAPINFOHEADER)lpDib)->biXPelsPerMeter = 0;
((LPBITMAPINFOHEADER)lpDib)->biYPelsPerMeter = 0;
((LPBITMAPINFOHEADER)lpDib)->biClrUsed = 0;
((LPBITMAPINFOHEADER)lpDib)->biClrImportant = 0;
// Figure out where the bits go
lpBits = (LPBYTE)lpDib+sizeof(BITMAPINFOHEADER)+iColorTable;
hDC = GetDC(hwndMain);
if (NULL != hDC)
{
if (bm.bmHeight == GetDIBits(hDC,hBitmap,0,
bm.bmHeight,lpBits,(LPBITMAPINFO)lpDib,
// DIB_PAL_INDICES))
DIB_RGB_COLORS))
{
BmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
BmpInfoHeader.biWidth = bm.bmWidth;
BmpInfoHeader.biHeight = bm.bmHeight;
BmpInfoHeader.biPlanes = wPlanes;
BmpInfoHeader.biBitCount = wBitCount;
BmpInfoHeader.biCompression = BI_RGB;
BmpInfoHeader.biSizeImage = dwSize;
BmpInfoHeader.biXPelsPerMeter = 0;
BmpInfoHeader.biYPelsPerMeter = 0;
BmpInfoHeader.biClrUsed = iColorUsed;
BmpInfoHeader.biClrImportant = iColorUsed;
hBmp = CreateDIBitmap(NULL, &BmpInfoHeader, CBM_INIT,
lpBits, (LPBITMAPINFO)lpDib, DIB_RGB_COLORS);
}
ReleaseDC(hwndMain, hDC);
}
GlobalUnlock(hDib);
}
GlobalFree(hDib);
}
return(hBmp);
}