Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2374 lines
62 KiB

/*****************************************************************************
C L I P B O O K D I S P L A Y
Name: clipdsp.c
Date: 21-Jan-1994
Creator: Unknown
Description:
This module handles the drawing of the clipbook displays.
*****************************************************************************/
#define WIN31
#include <windows.h>
#include <strsafe.h>
#include "common.h"
#include "clipbook.h"
#include "clpbkrc.h"
#include "clipbrd.h"
#include "clipdsp.h"
#include "debugout.h"
#include "cvutil.h"
#define ifmtMax (sizeof(rgfmt)/sizeof(WORD))
static MFENUMPROC lpEnumMetaProc;
BOOL fOwnerDisplay;
HBRUSH hbrBackground;
HMENU hDispMenu;
/* The scroll information for OWNER display is to be preserved, whenever
* the display changes between OWNER and NON-OWNER; The following globals
* are used to save and restore the scroll info.
*/
// winball: since only the Clipboard window supports owner display,
// this info is not replicated for each MDI child...
int OwnVerMin;
int OwnVerMax;
int OwnHorMin;
int OwnHorMax;
int OwnVerPos;
int OwnHorPos;
/* Defines priority order for show format */
WORD rgfmt[] = {
CF_OWNERDISPLAY,
CF_UNICODETEXT,
CF_TEXT,
CF_OEMTEXT,
CF_ENHMETAFILE,
CF_METAFILEPICT,
CF_DIB,
CF_BITMAP,
CF_DSPTEXT,
CF_DSPBITMAP,
CF_DSPMETAFILEPICT,
CF_DSPENHMETAFILE,
CF_PALETTE,
CF_RIFF,
CF_WAVE,
CF_PENDATA,
CF_SYLK,
CF_DIF,
CF_TIFF,
CF_LOCALE
};
void ShowString( HWND, HDC, WORD);
/*
* MyOpenClipBoard
*/
BOOL MyOpenClipboard(
HWND hWnd)
{
HDC hDC;
RECT Rect;
if( VOpenClipboard( GETMDIINFO(hWnd)->pVClpbrd, hWnd ))
return(TRUE);
PERROR(TEXT("MyOpenClipboard fail\r\n"));
/* Some app forgot to close the clipboard */
hDC = GetDC(hWnd);
GetClientRect(hWnd, (LPRECT)&Rect);
FillRect(hDC, (LPRECT)&Rect, hbrBackground);
ShowString( hWnd, hDC, IDS_ALREADYOPEN);
ReleaseDC(hWnd, hDC);
return(FALSE);
}
/*
* SetCharDimensions
*/
void SetCharDimensions(
HWND hWnd,
HFONT hFont)
{
register HDC hdc;
TEXTMETRIC tm;
PMDIINFO pMDI;
pMDI = GETMDIINFO(hWnd);
if (pMDI)
{
hdc = GetDC(hWnd);
SelectObject(hdc, hFont);
GetTextMetrics(hdc, (LPTEXTMETRIC)&tm);
ReleaseDC(hWnd, hdc);
pMDI->cxChar = (WORD)tm.tmAveCharWidth;
pMDI->cxMaxCharWidth = (WORD)tm.tmMaxCharWidth;
pMDI->cyLine = (WORD)(tm.tmHeight + tm.tmExternalLeading);
pMDI->cxMargin = pMDI->cxChar / 2;
pMDI->cyMargin = pMDI->cyLine / 4;
}
}
/*
* ChangeCharDimensions
*/
void ChangeCharDimensions(
HWND hwnd,
UINT wOldFormat,
UINT wNewFormat)
{
/* Check if the font has changed. */
if (wOldFormat == CF_OEMTEXT)
{
if (wNewFormat != CF_OEMTEXT) // Select default system font sizes
SetCharDimensions(hwnd, GetStockObject ( SYSTEM_FONT ) );
}
else if (wNewFormat == CF_OEMTEXT) // Select OEM font sizes
SetCharDimensions(hwnd, GetStockObject ( OEM_FIXED_FONT ) );
}
/*
* ClipbrdVScroll
*
* Scroll contents of window vertically, according to action code in wParam.
*/
void ClipbrdVScroll (
HWND hwnd,
WORD wParam,
WORD wThumb)
{
int cyWindow;
long dyScroll;
long cyScrollT;
long dyScrollAbs;
long cyPartialChar;
PMDIINFO pMDI;
pMDI = GETMDIINFO(hwnd);
if (pMDI)
{
/* Ensure that all the bits are valid first, before scrolling them */
UpdateWindow(hwnd);
cyScrollT = pMDI->cyScrollNow;
cyWindow = pMDI->rcWindow.bottom - pMDI->rcWindow.top;
/* Compute scroll results as an effect on cyScrollNow */
switch (wParam)
{
case SB_LINEUP:
cyScrollT -= pMDI->cyLine;
break;
case SB_LINEDOWN:
cyScrollT += pMDI->cyLine;
break;
case SB_THUMBPOSITION:
cyScrollT = (LONG)(((LONG)wThumb * pMDI->cyScrollLast) / VPOSLAST);
break;
case SB_PAGEUP:
case SB_PAGEDOWN:
{
int cyPageScroll;
cyPageScroll = cyWindow - pMDI->cyLine;
if (cyPageScroll < (int)(pMDI->cyLine))
cyPageScroll = pMDI->cyLine;
cyScrollT += (wParam == SB_PAGEUP) ? -cyPageScroll : cyPageScroll;
break;
}
default:
return;
}
if ((cyScrollT < 0) || (pMDI->cyScrollLast <= 0))
cyScrollT = 0;
else if (cyScrollT > pMDI->cyScrollLast)
cyScrollT = pMDI->cyScrollLast;
else if (cyPartialChar = cyScrollT % pMDI->cyLine)
{
/* Round to the nearest character increment. */
if (cyPartialChar > ((int)(pMDI->cyLine) >> 1))
cyScrollT += pMDI->cyLine;
cyScrollT -= cyPartialChar;
}
dyScroll = pMDI->cyScrollNow - cyScrollT;
if (dyScroll > 0)
dyScrollAbs = dyScroll;
else if (dyScroll < 0)
dyScrollAbs = -dyScroll;
else
return; /* Scrolling has no effect here. */
pMDI->cyScrollNow = cyScrollT;
if (dyScrollAbs >= pMDI->rcWindow.bottom - pMDI->rcWindow.top)
/* ScrollWindow does not handle this case */
InvalidateRect(hwnd, (LPRECT)&(pMDI->rcWindow), TRUE);
else
ScrollWindow(hwnd, 0,(int)dyScroll, &(pMDI->rcWindow), &(pMDI->rcWindow));
UpdateWindow(hwnd);
SetScrollPos (pMDI->hwndVscroll,
SB_CTL,
(pMDI->cyScrollLast <= 0) ?
0 :
(int)((cyScrollT * (DWORD)VPOSLAST) / pMDI->cyScrollLast),
TRUE);
}
}
/*
* ClipbrdHScroll
*
* Scroll contents of window horizontally, according to op code in wParam.
*/
void ClipbrdHScroll (
HWND hwnd,
WORD wParam,
WORD wThumb)
{
register int dxScroll;
register int cxScrollT;
int cxWindow;
int dxScrollAbs;
int cxPartialChar;
PMDIINFO pMDI;
pMDI = GETMDIINFO(hwnd);
if (pMDI)
{
cxScrollT = pMDI->cxScrollNow;
cxWindow = pMDI->rcWindow.right - pMDI->rcWindow.left;
/* Compute scroll results as an effect on cxScrollNow */
switch (wParam)
{
case SB_LINEUP:
cxScrollT -= pMDI->cxChar;
break;
case SB_LINEDOWN:
cxScrollT += pMDI->cxChar;
break;
case SB_THUMBPOSITION:
cxScrollT = (int)(((LONG)wThumb * (LONG)pMDI->cxScrollLast) / HPOSLAST);
break;
case SB_PAGEUP:
case SB_PAGEDOWN:
{
int cxPageScroll;
cxPageScroll = cxWindow - pMDI->cxChar;
if (cxPageScroll < (int)(pMDI->cxChar))
cxPageScroll = pMDI->cxChar;
cxScrollT += (wParam == SB_PAGEUP) ? -cxPageScroll : cxPageScroll;
break;
}
default:
return;
}
if ((cxScrollT < 0) || (pMDI->cxScrollLast <= 0))
cxScrollT = 0;
else if (cxScrollT > pMDI->cxScrollLast)
cxScrollT = pMDI->cxScrollLast;
else if (cxPartialChar = cxScrollT % pMDI->cxChar)
{ /* Round to the nearest character increment */
if (cxPartialChar > ((int)(pMDI->cxChar) >> 1))
cxScrollT += pMDI->cxChar;
cxScrollT -= cxPartialChar;
}
/* Now we have a good cxScrollT value */
dxScroll = pMDI->cxScrollNow - cxScrollT;
if (dxScroll > 0)
dxScrollAbs = dxScroll;
else if (dxScroll < 0)
dxScrollAbs = -dxScroll;
else
return; /* Scrolling has no effect here. */
pMDI->cxScrollNow = cxScrollT;
if (dxScrollAbs >= pMDI->rcWindow.right - pMDI->rcWindow.left)
/* ScrollWindow does not handle this case */
InvalidateRect( hwnd, (LPRECT) &(pMDI->rcWindow), TRUE );
else
ScrollWindow(hwnd, dxScroll, 0, (LPRECT)&(pMDI->rcWindow),
(LPRECT)&(pMDI->rcWindow));
UpdateWindow(hwnd);
SetScrollPos (pMDI->hwndHscroll,
SB_CTL,
(pMDI->cxScrollLast <= 0) ?
0 :
(int)(((DWORD)cxScrollT * (DWORD)HPOSLAST) / (DWORD)(pMDI->cxScrollLast)),
TRUE);
}
}
/*
* DibPaletteSize
*/
int DibPaletteSize(
LPBITMAPINFOHEADER lpbi)
{
register int bits;
register int nRet;
/* With the new format headers, the size of the palette is in biClrUsed
* else is dependent on bits per pixel.
*/
if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
{
if (lpbi->biClrUsed != 0)
{
nRet = lpbi->biClrUsed * sizeof(RGBQUAD);
}
else
{
bits = lpbi->biBitCount;
if (24 == bits)
{
nRet = 0;
}
else if (16 == bits || 32 == bits)
{
nRet = 3 * sizeof(DWORD);
}
else
{
nRet = (1 << bits) * sizeof(RGBQUAD);
}
}
}
else
{
bits = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
nRet = (bits == 24) ? 0 : (1 << bits) * sizeof(RGBTRIPLE);
}
return(nRet);
}
/*
* DibGetInfo
*/
void DibGetInfo(
HANDLE hdib,
LPBITMAP pbm)
{
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
{
pbm->bmWidth = (int)lpbi->biWidth;
pbm->bmHeight = (int)lpbi->biHeight;
}
else
{
pbm->bmWidth = (int)((LPBITMAPCOREHEADER)lpbi)->bcWidth;
pbm->bmHeight = (int)((LPBITMAPCOREHEADER)lpbi)->bcHeight;
}
GlobalUnlock(hdib);
}
/*
* DrawDib
*/
BOOL DrawDib(
HWND hwnd,
HDC hdc,
int x0,
int y0,
HANDLE hdib)
{
LPBITMAPINFOHEADER lpbi;
BITMAP bm;
LPSTR lpBits;
BOOL fOK = FALSE;
if (hdib)
{
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);
if (lpbi)
{
DibGetInfo(hdib, (LPBITMAP)&bm);
lpBits = (LPSTR)lpbi + (WORD)lpbi->biSize + DibPaletteSize(lpbi);
SetDIBitsToDevice (hdc,
x0,
y0,
bm.bmWidth,
bm.bmHeight,
0,
0,
0,
bm.bmHeight,
lpBits,
(LPBITMAPINFO)lpbi,
DIB_RGB_COLORS);
GlobalUnlock(hdib);
fOK = TRUE;
}
}
return(fOK);
}
/*
* FShowDIBitmap
*/
BOOL FShowDIBitmap (
HWND hwnd,
register HDC hdc,
PRECT prc,
HANDLE hdib, //Bitmap in DIB format
int cxScroll,
int cyScroll)
{
BITMAP bm;
PMDIINFO pMDI;
pMDI = GETMDIINFO(hwnd);
if (pMDI)
{
DibGetInfo(hdib, (LPBITMAP)&bm);
// If window's been resized, determine maximum scroll positions.
if (pMDI->cyScrollLast == -1)
{
/* Compute last scroll offset into bitmap */
pMDI->cyScrollLast = bm.bmHeight -
(pMDI->rcWindow.bottom - pMDI->rcWindow.top);
if (pMDI->cyScrollLast < 0)
{
pMDI->cyScrollLast = 0;
}
}
if (pMDI->cxScrollLast == -1)
{
/* Compute last scroll offset into bitmap */
pMDI->cxScrollLast = bm.bmWidth -
(pMDI->rcWindow.right - pMDI->rcWindow.left);
if (pMDI->cxScrollLast < 0)
{
pMDI->cxScrollLast = 0;
}
}
}
SaveDC(hdc);
IntersectClipRect (hdc, prc->left, prc->top, prc->right, prc->bottom);
SetViewportOrgEx (hdc,prc->left - cxScroll, prc->top - cyScroll,NULL);
DrawDib (hwnd, hdc, 0, 0, hdib);
RestoreDC(hdc, -1);
return(TRUE);
}
/*
* FShowBitmap
*/
BOOL FShowBitmap (
HWND hwnd,
HDC hdc,
register PRECT prc,
HBITMAP hbm,
int cxScroll,
int cyScroll)
{
register HDC hMemDC;
BITMAP bitmap;
int cxBlt, cyBlt;
int cxRect, cyRect;
PMDIINFO pMDI;
pMDI = GETMDIINFO(hwnd);
if ((hMemDC = CreateCompatibleDC(hdc)) == NULL)
return(FALSE);
if (!SelectObject(hMemDC, (HBITMAP)hbm))
{
DeleteDC(hMemDC);
ShowString( hwnd, hdc, IDS_BADBMPFMT );
return TRUE;
}
GetObject((HBITMAP)hbm, sizeof(BITMAP), (LPSTR)&bitmap);
if (pMDI->cyScrollLast == -1)
{
/* Compute last scroll offset into bitmap */
pMDI->cyScrollLast = bitmap.bmHeight - (pMDI->rcWindow.bottom - pMDI->rcWindow.top);
if (pMDI->cyScrollLast < 0)
pMDI->cyScrollLast = 0;
}
if ( pMDI->cxScrollLast == -1)
{
/* Compute last scroll offset into bitmap */
pMDI->cxScrollLast = bitmap.bmWidth - (pMDI->rcWindow.right - pMDI->rcWindow.left);
if ( pMDI->cxScrollLast < 0)
pMDI->cxScrollLast = 0;
}
cxRect = prc->right - prc->left;
cyRect = prc->bottom - prc->top;
cxBlt = min(cxRect, bitmap.bmWidth - cxScroll);
cyBlt = min(cyRect, bitmap.bmHeight - cyScroll);
BitBlt (hdc,
prc->left,
prc->top,
cxBlt,
cyBlt,
hMemDC,
cxScroll,
cyScroll, /* X,Y offset into source DC */
SRCCOPY);
DeleteDC(hMemDC);
return(TRUE);
}
#define DXPAL (pMDI->cyLine)
#define DYPAL (pMDI->cyLine)
////////////////////////////////////////////////////////////////////////////
//
// FShowPalette()
//
// Parameters:
// hwnd - The wMDI child we're drawing in.
// hdc - DC for the window.
// prc - Rectangle to draw.
// hpal - The palette to display.
// cxScroll, cyScroll - Scroll position in pels OF PRC. NOT OF THE WINDOW.
// Derive window scroll position by doing a cxScroll -= pMDI->cxScrollNow
//
////////////////////////////////////////////////////////////////////////////
BOOL FShowPalette(
HWND hwnd,
register HDC hdc,
register PRECT prc,
HPALETTE hpal,
int cxScroll,
int cyScroll)
{
int n;
int x, y;
int nx, ny;
int nNumEntries;
RECT rc;
HBRUSH hbr;
PMDIINFO pMDI;
BOOL fOK = FALSE;
TCHAR achHex[] = TEXT("0123456789ABCDEF");
int nFirstLineDrawn;
PINFO(TEXT("Palette: (%d,%d-%d,%d),cx %d, cy %d\r\n"),
prc->left, prc->top, prc->right, prc->bottom, cxScroll, cyScroll);
pMDI = GETMDIINFO(hwnd);
if (hpal)
{
// Correct cyScroll to show window's scroll position, not prc's.
cyScroll -= prc->top - pMDI->rcWindow.top;
PINFO(TEXT("Corrected cyScroll %d\r\n"), cyScroll);
// GetObject does not return an int-- it returns a USHORT. Thus,
// we zero out nNumEntries before getobjecting the palette.
nNumEntries = 0;
GetObject(hpal, sizeof(int), (LPSTR)&nNumEntries);
// Figure how many boxes across and tall the array of color boxes
// is
nx = ((pMDI->rcWindow.right - pMDI->rcWindow.left) / DXPAL);
if (nx == 0)
{
nx = 1;
}
ny = (nNumEntries + nx - 1) / nx;
PINFO(TEXT("%d entries, %d by %d array\r\n"), nNumEntries, nx, ny);
// If the window's been resized, we have to tell it how far you
// can scroll off to the right and down.
if ( pMDI->cyScrollLast == -1)
{
pMDI->cyScrollLast = ny * DYPAL - // Height of palette minus
pMDI->rcWindow.bottom - pMDI->rcWindow.top + // height of window plus
DYPAL; // one palette entry height.
if ( pMDI->cyScrollLast < 0)
{
pMDI->cyScrollLast = 0;
}
PINFO(TEXT("Last allowed scroll: %d\r\n"), pMDI->cyScrollLast);
}
if ( pMDI->cxScrollLast == -1)
{
/* Can't scroll palettes horizontally. */
pMDI->cxScrollLast = 0;
}
SaveDC(hdc);
IntersectClipRect(hdc, prc->left, prc->top, prc->right, prc->bottom);
SetWindowOrgEx(hdc, -pMDI->rcWindow.left, -pMDI->rcWindow.top, NULL);
// Set up the x and y positions of the first palette entry to draw
// and figure out which palette entry IS the first that needs drawing.
x = 0;
nFirstLineDrawn = (cyScroll + prc->top - pMDI->rcWindow.top)/ DYPAL;
n = nx * nFirstLineDrawn;
y = DYPAL * nFirstLineDrawn - cyScroll;
PINFO(TEXT("First entry %d at %d, %d\r\n"), n, x, y);
// While n < number of entries and the current entry isn't off the bottom
// of the window
while (n < nNumEntries && y < prc->bottom)
{
// Figure out a DXPAL by DYPAL rect going down/right from x,y
rc.left = x;
rc.top = y;
rc.right = rc.left + DXPAL;
rc.bottom = rc.top + DYPAL;
// PINFO(TEXT("(%d,%d) "), rc.left, rc.top);
// Draw a black box with the appropriate color inside.
if (RectVisible(hdc, &rc))
{
// PINFO(TEXT("<"));
// If you change this one to zero, you get a text display of
// the palette indices-- I used it to debug the draw code, 'cause
// it's near impossible, when you've got little colored
// squares, to figure out just which color is on the bottom of THAT
// square THERE, the one that was scrolled halfway off the bottom
// of the window, and you just scrolled it on. ("Well, it's sorta
// purple... of course, this entire palette is sorta purple..")
#if 1
InflateRect(&rc, -1, -1);
FrameRect(hdc, &rc, GetStockObject(BLACK_BRUSH));
InflateRect(&rc, -1, -1);
hbr = CreateSolidBrush(PALETTEINDEX(n));
FillRect(hdc, &rc, hbr);
DeleteObject(hbr);
#else
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc, rc.left + 2, rc.top + 2, &achHex[(n / 16)&0x0f], 1);
TextOut(hdc, (rc.left + rc.right) / 2, rc.top + 2,
&achHex[n & 0x0f], 1);
#endif
}
// Go to next entry and advance x to the next position, "word
// wrapping" to next line if we need to
n++;
x += DXPAL;
if (0 == n % nx)
{
x = 0;
y += DYPAL;
PINFO(TEXT("Wrap at %d\r\n"), n);
}
}
RestoreDC(hdc, -1);
fOK = TRUE;
}
else
{
PERROR(TEXT("Bad palette!\r\n"));
}
return(fOK);
}
/*
* PxlConvert
*
* Return the # of pixels spanned by 'val', a measurement in coordinates
* appropriate to mapping mode mm. 'pxlDeviceRes' gives the resolution
* of the device in pixels, along the axis of 'val'. 'milDeviceRes' gives
* the same resolution measurement, but in millimeters.
*/
int PxlConvert(
int mm,
int val,
int pxlDeviceRes,
int milDeviceRes)
{
register WORD wMult = 1;
register WORD wDiv = 1;
DWORD ulPxl;
DWORD ulDenom;
DWORD ulMaxInt = 0x7FFF;
if (milDeviceRes == 0)
{
/* to make sure we don't get divide-by-0 */
return(0);
}
switch (mm)
{
case MM_LOMETRIC:
wDiv = 10;
break;
case MM_HIMETRIC:
wDiv = 100;
break;
case MM_TWIPS:
wMult = 254;
wDiv = 14400;
break;
case MM_LOENGLISH:
wMult = 2540;
wDiv = 10000;
break;
case MM_HIENGLISH:
wMult = 254;
wDiv = 10000;
break;
case MM_TEXT:
return(val);
case MM_ISOTROPIC:
case MM_ANISOTROPIC:
/* These picture types have no original size */
default:
return(0);
}
/* Add denominator - 1 to numerator, to avoid roundoff */
ulDenom = (DWORD)wDiv * (DWORD)milDeviceRes;
ulPxl = (((DWORD)((DWORD)wMult * (DWORD)val * (DWORD)pxlDeviceRes)) + ulDenom - 1) / ulDenom;
return((ulPxl > ulMaxInt) ? 0 : (int)ulPxl);
}
/*
* FShowEnhMetaFile
*
* Display an enhanced metafile in the specified rectangle.
*/
BOOL FShowEnhMetaFile(
HWND hwnd,
register HDC hdc,
register PRECT prc,
HANDLE hemf,
int cxScroll,
int cyScroll)
{
int cxBitmap;
int cyBitmap;
RECT rcWindow;
int f = FALSE;
PMDIINFO pMDI;
pMDI = GETMDIINFO(hwnd);
if (pMDI)
{
/* Not scrollable. Resize these into the given rect. */
pMDI->cyScrollLast = 0;
pMDI->cxScrollLast = 0;
cxBitmap = pMDI->rcWindow.right - pMDI->rcWindow.left;
cyBitmap = pMDI->rcWindow.bottom - pMDI->rcWindow.top;
/* We make the "viewport" to be an area the same size as the
* clipboard object, and set the origin and clip region so as
* to show the area we want. Note that the viewport may well be
* bigger than the window.
*/
SetMapMode(hdc, MM_TEXT);
rcWindow.left = prc->left - cxScroll;
rcWindow.top = prc->top - cyScroll;
rcWindow.right = rcWindow.left + cxBitmap;
rcWindow.bottom = rcWindow.top + cyBitmap;
f = PlayEnhMetaFile (hdc, hemf, &rcWindow);
// Always return TRUE. PlayEnhMetaFile() can return
// FALSE even when the metafile can be displayed
// properly. Things such as printer escap can cause
// the call to return FALSE when painting to screen
// but the image will be displayed fine.
//
// We return TRUE so we don't blank the display and
// put "Clipbook can't display..." message.
}
return TRUE;
}
/*
* EnumMetafileProc
*
* Metafile record play callback function used to work around problem
* with non active MDI children playing a metafile that causes a foreground
* palette selection
*/
BOOL CALLBACK EnumMetafileProc (
HDC hdc,
HANDLETABLE FAR *lpht,
METARECORD FAR *lpmr,
int cObj,
LPARAM lParam )
{
if ( lpmr->rdFunction == META_SELECTPALETTE )
{
return SelectPalette ( hdc, lpht[(lpmr->rdParm[0])].objectHandle[0],
TRUE ) != NULL;
}
else
{
PlayMetaFileRecord ( hdc, lpht, lpmr, cObj );
return TRUE;
}
}
/*
* FShowMetaFilePict
*
* Display a metafile in the specified rectangle.
*/
BOOL FShowMetaFilePict(
HWND hwnd,
register HDC hdc,
register PRECT prc,
HANDLE hmfp,
int cxScroll,
int cyScroll)
{
int level;
int cxBitmap;
int cyBitmap;
int f = FALSE;
LPMETAFILEPICT lpmfp;
PMDIINFO pMDI;
pMDI = GETMDIINFO(hwnd);
if (pMDI)
{
if ((lpmfp = (LPMETAFILEPICT)GlobalLock( hmfp )) != NULL)
{
METAFILEPICT mfp;
mfp = *lpmfp;
GlobalUnlock( hmfp );
if ((level = SaveDC( hdc )) != 0)
{
/* Compute size of picture to be displayed */
switch (mfp.mm)
{
case MM_ISOTROPIC:
case MM_ANISOTROPIC:
/* Not scrollable. Resize these into the given rect. */
pMDI->cyScrollLast = 0;
pMDI->cxScrollLast = 0;
cxBitmap = pMDI->rcWindow.right - pMDI->rcWindow.left;
cyBitmap = pMDI->rcWindow.bottom - pMDI->rcWindow.top;
break;
default:
cxBitmap = PxlConvert(mfp.mm, mfp.xExt, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, HORZSIZE));
cyBitmap = PxlConvert(mfp.mm, mfp.yExt, GetDeviceCaps(hdc, VERTRES), GetDeviceCaps(hdc, VERTSIZE));
if (!cxBitmap || !cyBitmap)
{
goto NoDisplay;
}
if ( pMDI->cxScrollLast == -1)
{
pMDI->cxScrollLast =
cxBitmap - (pMDI->rcWindow.right - pMDI->rcWindow.left);
if ( pMDI->cxScrollLast < 0)
{
pMDI->cxScrollLast = 0;
}
}
if (pMDI->cyScrollLast == -1)
{
pMDI->cyScrollLast =
cyBitmap - (pMDI->rcWindow.bottom - pMDI->rcWindow.top);
if (pMDI->cyScrollLast < 0)
{
pMDI->cyScrollLast = 0;
}
}
break;
}
/* We make the "viewport" to be an area the same size as the
* clipboard object, and set the origin and clip region so as
* to show the area we want. Note that the viewport may well be
* bigger than the window.
*/
SetMapMode(hdc, mfp.mm);
SetViewportOrgEx(hdc, prc->left - cxScroll, prc->top - cyScroll, NULL);
switch (mfp.mm)
{
case MM_ISOTROPIC:
if (mfp.xExt && mfp.yExt)
{
// So we get the correct shape rectangle when
// SetViewportExt gets called.
//
SetWindowExtEx(hdc, mfp.xExt, mfp.yExt, NULL);
}
// FALL THRU
case MM_ANISOTROPIC:
SetViewportExtEx(hdc, cxBitmap, cyBitmap, NULL);
break;
}
/* Since we may have scrolled, force brushes to align */
SetBrushOrgEx(hdc, cxScroll - prc->left, cyScroll - prc->top, NULL);
f = EnumMetaFile(hdc, mfp.hMF, EnumMetafileProc, 0L );
FreeProcInstance ( (FARPROC) lpEnumMetaProc );
NoDisplay:
RestoreDC(hdc, level);
}
}
}
return(f);
}
/*
* ShowString
*
* Blank rcWindow and show the string on the top line of the client area
*/
void ShowString(
HWND hwnd,
HDC hdc,
WORD id)
{
TCHAR szBuffer[BUFFERLEN];
LPTSTR pszBuffer = szBuffer;
INT iBufferSize = BUFFERLEN;
INT iStringLen;
/* Cancel any scrolling effects. */
GETMDIINFO(hwnd)->cyScrollNow = 0;
GETMDIINFO(hwnd)->cxScrollNow = 0;
iStringLen = LoadString(hInst, id, pszBuffer, BUFFERLEN);
// Is the buffer completely filled out?
// We need a bigger one if yes.
while (iStringLen == BUFFERLEN -1)
{
if (pszBuffer != szBuffer && pszBuffer)
LocalFree (pszBuffer);
iBufferSize *= 2;
pszBuffer = LocalAlloc (LPTR, iBufferSize);
if (!pszBuffer)
goto done;
iStringLen = LoadString (hInst, id, pszBuffer, iBufferSize);
}
FillRect (hdc, &(GETMDIINFO(hwnd)->rcWindow), hbrBackground);
DrawText (hdc, pszBuffer, -1, &(GETMDIINFO(hwnd)->rcWindow),
DT_CENTER | DT_WORDBREAK | DT_TOP);
done:
if (pszBuffer != szBuffer && pszBuffer)
LocalFree (pszBuffer);
}
/*
* CchLineA
*
*
* Determine the # of characters in one display line's worth of lpch.
* lpch is assumed to be an ansi string.
*
* Return the following:
* HI WORD: # of chars to display (excludes CR, LF; will not
* exceed cchLine)
* LO WORD: offset of start of next line in lpch; If the current line
* is NULL terminated, this contains offset to the NULL char;
* In RgchBuf: characters to display
*
* Expands Tabs
*
* Accepts any of the following as valid end-of-line terminators:
* CR, LF, CR-LF, LF-CR, NULL
* Callers may test for having reached NULL by (lpch[LOWORD] == '\0')
*/
LONG CchLineA(
PMDIINFO pMDI,
HDC hDC,
CHAR rgchBuf[],
CHAR FAR *lpch,
INT cchLine,
WORD wWidth)
{
CHAR ch;
CHAR *pch = rgchBuf;
register INT cchIn = 0;
register INT cchOut = 0;
INT iMinNoOfChars;
SIZE size;
INT iTextWidth = 0;
iMinNoOfChars = wWidth / pMDI->cxMaxCharWidth;
while (cchOut < cchLine)
{
switch (ch = *(lpch + (DWORD)cchIn++))
{
case '\0':
/* cchIn is already incremented; So, it is pointing to
* a character beyond the NULL; So, decrement it.
*/
cchIn--;
goto DoubleBreak;
case '\015': /* CR */
case '\012': /* LF */
if ((lpch[cchIn] == '\015') || (lpch[cchIn] == '\012'))
cchIn++;
goto DoubleBreak;
case '\011': /* TAB */
{
INT cchT = 8 - (cchOut % 8);
/* Check if the width has exceeded or the total
* number of characters has exceeded
*/
if (((WORD)(iTextWidth + cchT * pMDI->cxChar) > wWidth) || ((cchOut+cchT) >= cchLine))
/* Tab causes wrap to next line */
goto DoubleBreak;
while (cchT--)
rgchBuf[cchOut++] = ' ';
break;
}
default:
rgchBuf[cchOut++] = ch;
if( IsDBCSLeadByte(ch) )
rgchBuf[cchOut++] = *(lpch + (DWORD)cchIn++);
break;
}
/* Check if the width has been exceeded. */
if (cchOut >= iMinNoOfChars)
{
GetTextExtentPointA(hDC, rgchBuf, cchOut, (LPSIZE)&size);
iTextWidth = size.cx;
if ((WORD)iTextWidth == wWidth)
break;
else if((WORD)iTextWidth > wWidth)
{
if (IsDBCSLeadByte(ch))
{
cchOut--;
cchIn--;
}
cchOut--;
cchIn--;
break;
}
iMinNoOfChars += (wWidth - iTextWidth) / pMDI->cxMaxCharWidth;
}
}
DoubleBreak:
return(MAKELONG(cchIn, cchOut));
}
/*--------------------------------------------------------------------------*/
/* */
/* CchLineW() - */
/* */
/*--------------------------------------------------------------------------*/
/*Same as previous function but takes unicode strings.
*/
LONG CchLineW(
PMDIINFO pMDI,
HDC hDC,
WCHAR rgchBuf[],
WCHAR FAR *lpch,
INT cchLine,
WORD wWidth)
{
register INT cchIn = 0;
register INT cchOut = 0;
WCHAR ch;
WCHAR *pch = rgchBuf;
INT iMinNoOfChars;
INT iTextWidth = 0;
SIZE size;
iMinNoOfChars = wWidth / pMDI->cxMaxCharWidth;
while (cchOut < cchLine)
{
switch (ch = *(lpch + (DWORD)cchIn++))
{
case L'\0':
/* cchIn is already incremented; So, it is pointing to
* a character beyond the NULL; So, decrement it.
*/
cchIn--;
goto DoubleBreak;
case L'\015': /* CR */
case L'\012': /* LF */
if ((lpch[cchIn] == L'\015') || (lpch[cchIn] == L'\012'))
cchIn++;
goto DoubleBreak;
case L'\011': /* TAB */
{
INT cchT = 8 - (cchOut % 8);
/* Check if the width has exceeded or the total
* number of characters has exceeded
*/
if (((WORD)(iTextWidth + cchT * pMDI->cxChar) > wWidth) || ((cchOut+cchT) >= cchLine))
/* Tab causes wrap to next line */
goto DoubleBreak;
while (cchT--)
rgchBuf[cchOut++] = L' ';
break;
}
default:
rgchBuf[cchOut++] = ch;
break;
}
/* Check if the width has been exceeded. */
if (cchOut >= iMinNoOfChars)
{
GetTextExtentPointW(hDC, rgchBuf, cchOut, &size);
iTextWidth = size.cx;
if ((WORD)iTextWidth == wWidth)
break;
else if((WORD)iTextWidth > wWidth)
{
cchOut--;
cchIn--;
break;
}
iMinNoOfChars += (wWidth - iTextWidth) / pMDI->cxMaxCharWidth;
}
}
DoubleBreak:
return(MAKELONG(cchIn, cchOut));
}
#define cchLineMax 200
/*--------------------------------------------------------------------------*/
/* */
/* ShowText() - */
/* */
/*--------------------------------------------------------------------------*/
void ShowText(
HWND hwnd,
register HDC hdc,
PRECT prc,
HANDLE h,
INT cyScroll,
BOOL fUnicode)
{
CHAR FAR *lpch;
INT yT;
INT cLine;
INT cLineAllText = 0;
RECT rc;
INT yLine;
INT iLineFirstShow;
WORD wLen;
WORD wWidth;
CHAR rgch[cchLineMax*sizeof(WCHAR)];
PMDIINFO pMDI;
pMDI= GETMDIINFO(hwnd);
rc = *prc;
/* Expand repaint rectangle as necessary to hold an exact number of
* lines and start on an even line boundary. This is because we may
* get arbitrarily weird repaint rectangles when popups are moved.
* Scrolling repaint areas should require no adjustment.
*/
rc.top -= (rc.top - pMDI->rcWindow.top) % pMDI->cyLine;
/* If expanding the repaint rectangle to the next line expands it */
/* beyond the bottom of my window, contract it one line. */
if ((yT = (rc.bottom - rc.top) % pMDI->cyLine) != 0)
if ((rc.bottom += pMDI->cyLine - yT) > pMDI->rcWindow.bottom)
rc.bottom -= pMDI->cyLine;
if (rc.bottom <= rc.top)
return;
if (((wWidth = (WORD)(pMDI->rcWindow.right - pMDI->rcWindow.left)) <= 0) ||
((cLine = (rc.bottom - rc.top) / pMDI->cyLine) <= 0) ||
(NULL == (lpch = (LPSTR)GlobalLock(h))) )
{
/* Bad Rectangle or Bad Text Handle */
ShowString(hwnd, hdc, IDS_ERROR);
return;
}
/* Advance lpch to point at the text for the first line to show. */
iLineFirstShow = cyScroll / pMDI->cyLine;
/* Advance lpch to point at text for that line. */
if (!fUnicode)
while ((*lpch) && (iLineFirstShow--))
{
lpch += LOWORD(CchLineA(pMDI,hdc, rgch, lpch, cchLineMax, wWidth));
cLineAllText++;
}
else
while ((*((WCHAR *)lpch)) && (iLineFirstShow--))
{
lpch += ((LOWORD(CchLineW(pMDI, hdc, (WCHAR *)rgch, (WCHAR FAR *)lpch,
cchLineMax, wWidth)))*sizeof(WCHAR));
cLineAllText++;
}
/* Display string, line by line */
yLine = rc.top;
while (cLine--)
{
LONG lT;
if (!fUnicode)
{
lT = CchLineA(pMDI, hdc, rgch, lpch, cchLineMax, wWidth);
}
else
{
lT = CchLineW(pMDI, hdc, (WCHAR *)rgch, (WCHAR FAR *)lpch, cchLineMax, wWidth);
}
wLen = LOWORD(lT);
if (!fUnicode)
{
TextOutA(hdc, rc.left, yLine, (LPSTR) rgch, HIWORD(lT));
lpch += wLen;
}
else
{
if (!TextOutW(hdc, rc.left, yLine, (LPCWSTR) rgch, HIWORD(lT)))
{
GetLastError();
}
lpch += (wLen * sizeof(WCHAR));
}
yLine += pMDI->cyLine;
cLineAllText++;
if ((!fUnicode && (*lpch == 0)) || (fUnicode && (*((WCHAR *)lpch) == L'\0')))
{
break;
}
}
if (pMDI->cxScrollLast == -1)
{
/* We don't use horiz scroll for text */
pMDI->cxScrollLast = 0;
}
if (pMDI->cyScrollLast == -1)
{
INT cLineInRcWindow;
/* Validate y-size of text in clipboard. */
/* Adjust rcWindow dimensions for text display */
cLineInRcWindow = (pMDI->rcWindow.bottom - pMDI->rcWindow.top) / pMDI->cyLine;
do {
if (!fUnicode)
{
lpch += LOWORD(CchLineA(pMDI, hdc, rgch, lpch, cchLineMax, wWidth));
}
else
{
lpch += ((LOWORD(CchLineW(pMDI, hdc, (WCHAR *)rgch,
(WCHAR FAR *)lpch, cchLineMax, wWidth)))*sizeof(WCHAR));
}
cLineAllText++;
}
while ((!fUnicode && (*lpch != 0)) || (fUnicode && ((*lpch != 0) || (*(lpch+1) != 0))));
pMDI->cyScrollLast = (cLineAllText - cLineInRcWindow) * pMDI->cyLine;
if (pMDI->cyScrollLast < 0)
{
pMDI->cyScrollLast = 0;
}
/* Restrict rcWindow so that it holds an exact # of text lines */
pMDI->rcWindow.bottom = pMDI->rcWindow.top + (cLineInRcWindow * pMDI->cyLine);
}
GlobalUnlock(h);
}
/*
* SendOwnerMessage
*/
void SendOwnerMessage(
UINT message,
WPARAM wParam,
LPARAM lParam)
{
register HWND hwndOwner;
/* Send a message to the clipboard owner, if there is one */
hwndOwner = GetClipboardOwner();
if (hwndOwner != NULL)
SendMessage(hwndOwner, message, wParam, lParam);
}
/*
* SendOwnerSizeMessage
*
* Send WM_SIZECLIPBOARD message to clipboard owner.
* wParam is a handle to the clipboard window
* LOWORD(lParam) is a handle to the passed rect
*/
void SendOwnerSizeMessage (
HWND hwnd,
int left,
int top,
int right,
int bottom)
{
register HANDLE hrc;
LPRECT lprc;
if ((hrc = GlobalAlloc (GMEM_MOVEABLE | GMEM_LOWER, (LONG)sizeof(RECT))) != NULL )
{
if ((lprc = (LPRECT)GlobalLock(hrc)) != NULL )
{
lprc->top = top;
lprc->bottom = bottom;
lprc->left = left;
lprc->right = right;
GlobalUnlock(hrc);
SendOwnerMessage(WM_SIZECLIPBOARD, (WPARAM)hwnd, (LPARAM)hrc);
}
GlobalFree(hrc);
}
}
/*
* GetBestFormat
*
* This routine decides which one of the existing formats is to be
* displayed in the viewer.
*/
UINT GetBestFormat(
HWND hwnd,
UINT wFormat)
{
register WORD cFmt;
register WORD *pfmt;
// PINFO(TEXT("GBFormat %d\r\n"), wFormat);
if (wFormat == CBM_AUTO)
{
for (cFmt=ifmtMax, pfmt=&rgfmt[0]; cFmt--; pfmt++)
{
// PINFO(TEXT("Looking at # %d, (%d)\r\n"), cFmt, *pfmt);
if ( VIsClipboardFormatAvailable( GETMDIINFO(hwnd)->pVClpbrd, *pfmt ))
{
return(*pfmt);
}
}
return(0);
}
return(wFormat);
}
/*
* GetClipboardName
*/
void GetClipboardName (
register int fmt,
LPTSTR szName,
register int iSize)
{
LPTSTR lprgch;
HANDLE hrgch;
*szName = '\0';
/* Get global memory that everyone can get to */
if ((hrgch = GlobalAlloc(GMEM_MOVEABLE | GMEM_LOWER, (LONG)(iSize + 1))) == NULL)
{
PERROR(TEXT("GetClipboardName: alloc failure\n\r"));
return;
}
if (!(lprgch = (LPTSTR)GlobalLock(hrgch)))
goto ExitPoint;
switch (fmt)
{
// These are all of the formats we have know the names of.
case CF_RIFF:
case CF_WAVE:
case CF_PENDATA:
case CF_SYLK:
case CF_DIF:
case CF_TIFF:
case CF_TEXT:
case CF_UNICODETEXT:
case CF_OEMTEXT:
case CF_DSPTEXT:
case CF_LOCALE:
case CF_BITMAP:
case CF_DIB:
case CF_PALETTE:
case CF_DSPBITMAP:
case CF_METAFILEPICT:
case CF_DSPMETAFILEPICT:
case CF_ENHMETAFILE:
case CF_DSPENHMETAFILE:
case CF_HDROP:
LoadString(hInst, fmt, lprgch, iSize);
break;
case CF_OWNERDISPLAY: /* Clipbrd owner app supplies name */
*lprgch = '\0';
SendOwnerMessage(WM_ASKCBFORMATNAME, (WPARAM)iSize, (LPARAM)(LPSTR)lprgch);
if (!*lprgch)
LoadString(hInst, fmt, lprgch, iSize);
break;
default:
*lprgch = '\0';
GetClipboardFormatName(fmt, lprgch, iSize);
break;
}
StringCchCopy(szName, iSize, lprgch);
GlobalUnlock(hrgch);
ExitPoint:
GlobalFree(hrgch);
}
/*
* GetClipboardMenuName
*/
void GetClipboardMenuName (
register int fmt,
LPTSTR szName,
register int iSize)
{
LPTSTR lprgch;
HANDLE hrgch;
*szName = '\0';
/* Get global memory that everyone can get to */
if ((hrgch = GlobalAlloc(GMEM_MOVEABLE | GMEM_LOWER, (LONG)(iSize + 1))) == NULL)
{
PERROR(TEXT("GetClipboardName: alloc failure\n\r"));
return;
}
if (!(lprgch = (LPTSTR)GlobalLock(hrgch)))
goto ExitPoint;
switch (fmt)
{
// These are all of the formats we have know the names of.
case CF_RIFF:
case CF_WAVE:
case CF_PENDATA:
case CF_SYLK:
case CF_DIF:
case CF_TIFF:
case CF_TEXT:
case CF_UNICODETEXT:
case CF_OEMTEXT:
case CF_DSPTEXT:
case CF_BITMAP:
case CF_DIB:
case CF_PALETTE:
case CF_DSPBITMAP:
case CF_METAFILEPICT:
case CF_DSPMETAFILEPICT:
case CF_ENHMETAFILE:
case CF_DSPENHMETAFILE:
case CF_HDROP:
case CF_LOCALE:
LoadString(hInst, fmt+MNDELTA, lprgch, iSize);
break;
case CF_OWNERDISPLAY: /* Clipbrd owner app supplies name */
*lprgch = '\0';
SendOwnerMessage(WM_ASKCBFORMATNAME, (WPARAM)iSize, (LPARAM)(LPSTR)lprgch);
if (!*lprgch)
LoadString(hInst, CF_MN_OWNERDISPLAY, lprgch, iSize);
break;
default:
GetClipboardFormatName(fmt, lprgch, iSize);
break;
}
StringCchCopy(szName, iSize, lprgch);
GlobalUnlock(hrgch);
ExitPoint:
GlobalFree(hrgch);
}
/*
* DrawFormat
*
* Parameters:
* hdc - the hdc to draw in.
* prc - The rectangle to paint
* cxScroll - The scroll position of the window.
* cyScroll - The scroll position OF THE PAINT RECTANGLE. NOT THE WINDOW.
* (Gawd. Who DESIGNED this?) Measured in pels.
* BestFormat - The format to draw.
* hwndMDI - The window we're drawing in.
*
*/
void DrawFormat(
register HDC hdc,
PRECT prc,
int cxScroll,
int cyScroll,
WORD BestFormat,
HWND hwndMDI)
{
register HANDLE h;
HFONT hFont;
int fOK = TRUE;
WORD wFormat = 0;
PMDIINFO pMDI;
pMDI = GETMDIINFO(hwndMDI);
PINFO(TEXT("DrawFormat: (%d, %d), %d"), cxScroll, cyScroll, BestFormat);
if (hwndMDI == hwndClpbrd && pMDI->pVClpbrd)
{
PERROR(TEXT("Clipboard window shouldn't have vClp!\r\n"));
}
/* If "Auto" is chosen and only data in unrecognised formats is
* available, then display "Can't display data in this format".
*/
if ((BestFormat == 0) &&
VCountClipboardFormats( pMDI->pVClpbrd ))
{
if ((wFormat = (WORD)RegisterClipboardFormat(TEXT("FileName"))) &&
VIsClipboardFormatAvailable(pMDI->pVClpbrd, wFormat))
{
BestFormat = CF_TEXT;
}
else
{
PINFO(TEXT("no displayable format\n\r"));
ShowString( hwndMDI, hdc, IDS_CANTDISPLAY);
return;
}
}
PINFO(TEXT("format %x\n\r"), BestFormat);
h = VGetClipboardData( pMDI->pVClpbrd, wFormat ? wFormat : BestFormat );
if ( h != NULL)
{
PINFO(TEXT("Got format %x from VGetClipboardData\n\r"), BestFormat );
switch (BestFormat)
{
case CF_DSPTEXT:
case CF_TEXT:
ShowText( hwndMDI, hdc, prc, h, cyScroll, FALSE);
break;
case CF_UNICODETEXT:
hFont = SelectObject(hdc, hfontUni);
ShowText(hwndMDI, hdc, prc, h, cyScroll, TRUE);
SelectObject(hdc, hFont);
break;
case CF_OEMTEXT:
hFont = SelectObject(hdc, GetStockObject ( OEM_FIXED_FONT ) );
ShowText(hwndMDI, hdc, prc, h, cyScroll, FALSE);
SelectObject(hdc, hFont);
break;
case CF_DSPBITMAP:
case CF_BITMAP:
fOK = FShowBitmap( hwndMDI, hdc, prc, h, cxScroll, cyScroll);
break;
case CF_DIB:
fOK = FShowDIBitmap( hwndMDI, hdc, prc, h, cxScroll, cyScroll);
break;
case CF_PALETTE:
fOK = FShowPalette( hwndMDI, hdc, prc, h, cxScroll, cyScroll);
break;
case CF_WAVE:
case CF_RIFF:
case CF_PENDATA:
case CF_DIF:
case CF_SYLK:
case CF_TIFF:
case CF_LOCALE:
ShowString( hwndMDI, hdc, IDS_BINARY);
break;
case CF_DSPMETAFILEPICT:
case CF_METAFILEPICT:
fOK = FShowMetaFilePict( hwndMDI, hdc, prc, h, cxScroll, cyScroll);
break;
case CF_DSPENHMETAFILE:
case CF_ENHMETAFILE:
fOK = FShowEnhMetaFile( hwndMDI, hdc, prc, h, cxScroll, cyScroll);
break;
default:
ShowString( hwndMDI, hdc, IDS_BINARY);
break;
}
// Disable scroll bars that don't work
EnableWindow(pMDI->hwndVscroll, pMDI->cyScrollLast > 1 ? TRUE : FALSE);
EnableWindow(pMDI->hwndHscroll, pMDI->cxScrollLast > 1 ? TRUE : FALSE);
}
else
{
PERROR(TEXT("VGetClpDta fail\r\n"));
}
/* Check if the Data was not rendered by the application */
if ((h == NULL) &&
VCountClipboardFormats( pMDI->pVClpbrd ))
{
ShowString( hwndMDI, hdc, IDS_NOTRENDERED);
}
else
{
/* If we are unable to display the data, display "<Error>" */
if (!fOK)
{
ShowString( hwndMDI, hdc, IDS_ERROR);
}
}
}
/*
* DrawStuff
*
* Paint portion of current clipboard contents given by PAINT struct
* NOTE: If the paintstruct rectangle includes any part of the header, the
* whole header is redrawn.
*/
void DrawStuff(
HWND hwnd,
register PAINTSTRUCT *pps,
HWND hwndMDI)
{
register HDC hdc;
RECT rcPaint;
RECT rcClient;
WORD BestFormat;
PMDIINFO pMDI;
pMDI = GETMDIINFO(hwnd);
if (pMDI)
{
hdc = pps->hdc;
if (pps->fErase)
FillRect(hdc, (LPRECT)&pps->rcPaint, hbrBackground);
GetClientRect(hwnd, (LPRECT)&rcClient);
// make room for scroll controls:
BestFormat = (WORD)GetBestFormat( hwnd, pMDI->CurSelFormat );
fOwnerDisplay = (BestFormat == CF_OWNERDISPLAY);
if ( !fOwnerDisplay )
{
ShowScrollBar ( hwnd, SB_BOTH, FALSE );
rcClient.right -= GetSystemMetrics ( SM_CXVSCROLL );
rcClient.bottom -= GetSystemMetrics ( SM_CYHSCROLL );
}
/* If the display format has changed, Set rcWindow,
* the display area for clip info.
*/
if ( pMDI->fDisplayFormatChanged )
{
CopyRect((LPRECT)&(pMDI->rcWindow), (LPRECT)&rcClient);
/* We have changed the size of the clipboard. Tell the owner,
* if fOwnerDisplay is active.
*/
if (fOwnerDisplay)
{
SendOwnerSizeMessage(hwnd,
pMDI->rcWindow.left,
pMDI->rcWindow.top,
pMDI->rcWindow.right,
pMDI->rcWindow.bottom);
}
else
{
/* Give the window a small margin, for looks */
InflateRect (&(pMDI->rcWindow),
-(int)(pMDI->cxMargin),
-(int)(pMDI->cyMargin));
}
pMDI->fDisplayFormatChanged = FALSE;
}
if (fOwnerDisplay)
{
/* Clipboard Owner handles display */
HANDLE hps;
hps = GlobalAlloc(GMEM_MOVEABLE | GMEM_LOWER, (LONG)sizeof(PAINTSTRUCT));
if (hps != NULL)
{
LPPAINTSTRUCT lppsT;
if ((lppsT = (LPPAINTSTRUCT)GlobalLock(hps)) != NULL)
{
*lppsT = *pps;
IntersectRect(&lppsT->rcPaint, &pps->rcPaint, &(pMDI->rcWindow));
GlobalUnlock(hps);
SendOwnerMessage(WM_PAINTCLIPBOARD, (WPARAM)hwnd, (LPARAM)hps);
GlobalFree(hps);
}
}
}
else
{
/* We handle display */
/* Redraw the portion of the paint rectangle that is in the clipbrd rect */
IntersectRect(&rcPaint, &pps->rcPaint, &(pMDI->rcWindow));
/* Always draw from left edge of window */
rcPaint.left = pMDI->rcWindow.left;
if ((rcPaint.bottom > rcPaint.top) && (rcPaint.right > rcPaint.left))
{
DrawFormat (hdc,
&rcPaint,
(int)(pMDI->cxScrollNow),
(int)(pMDI->cyScrollNow + rcPaint.top - pMDI->rcWindow.top),
BestFormat,
hwndMDI );
}
}
}
}
/*
* SaveOwnerScrollInfo
*
* When the user switched the clipboard display from owner disp to
* a non-owner display, all the information about the scroll bar
* positions are to be saved. This routine does that.
* This is required because, when the user returns back to owner
* display, the scroll bar positions are to be restored.
*/
void SaveOwnerScrollInfo (
register HWND hwnd)
{
GetScrollRange (hwnd, SB_VERT, (LPINT) & OwnVerMin, (LPINT) & OwnVerMax);
GetScrollRange (hwnd, SB_HORZ, (LPINT) & OwnHorMin, (LPINT) & OwnHorMax);
OwnVerPos = GetScrollPos( hwnd, SB_VERT );
OwnHorPos = GetScrollPos( hwnd, SB_HORZ );
}
/*
* RestoreOwnerScrollInfo
*
* When the user sitches back to owner-display, the scroll bar
* positions are restored by this routine.
*/
void RestoreOwnerScrollInfo (
register HWND hwnd)
{
PINFO(TEXT("SETSCROLLRANGE in RestoreOwnerScrollInfo\n\r"));
SetScrollRange( hwnd, SB_VERT, OwnVerMin, OwnVerMax, FALSE);
SetScrollRange( hwnd, SB_HORZ, OwnHorMin, OwnHorMax, FALSE);
SetScrollPos( hwnd, SB_VERT, OwnVerPos, TRUE);
SetScrollPos( hwnd, SB_HORZ, OwnHorPos, TRUE);
}
/*
* InitOwnerScrollInfo
*/
void InitOwnerScrollInfo(void)
{
OwnVerPos = OwnHorPos = OwnVerMin = OwnHorMin = 0;
OwnVerMax = VPOSLAST;
OwnHorMax = HPOSLAST;
}
/*
* UpdateCBMenu
*
* This routine is called once during initialisation and everytime
* the contents of the clipboard change. This updates the entries
* in the "Display" popup menu and the "grey" and "checked" status
* based on the data formats available in the clipboard.
*/
void UpdateCBMenu(
HWND hwnd,
HWND hwndMDI)
{
register WORD wFlags; // Used to store the status flags for menu items
register UINT fmt;
WORD cFmt;
WORD cCBCount; // Number of data items in CB
int iIndex;
int nPopupCount;
BOOL bAutoSelect;
TCHAR szName[40];
// Now clipboard contains at least one item...
// Find out the number entries in the popup menu at present.
// make sure child window is valid
if ( !hwndMDI || !IsWindow(hwndMDI))
{
PERROR(TEXT("bad window arg to UpdateCBMenu\n\r"));
return;
}
nPopupCount = GetMenuItemCount(hDispMenu);
if (nPopupCount > 6)
{
// Delete all the entries in the popup menu below menu break. */
for (iIndex = 6; iIndex < nPopupCount; iIndex++)
{
// NOTE: The second parameter must always be 6! (because we use
// MF_BYPOSITION, when 6 is deleted, 7 becomes 6!).
DeleteMenu(hDispMenu, 6, MF_BYPOSITION | MF_DELETE);
}
}
// If this is not a page MDI window we don't want to show any entries
if ( GETMDIINFO(hwndMDI)->DisplayMode != DSP_PAGE )
{
return;
}
bAutoSelect = TRUE;
if ((cCBCount = (WORD)VCountClipboardFormats( GETMDIINFO(hwndMDI)->pVClpbrd ))
&& VOpenClipboard( GETMDIINFO(hwndMDI)->pVClpbrd, hwnd))
{
AppendMenu ( hDispMenu, MF_SEPARATOR, 0, 0 );
AppendMenu ( hDispMenu, MF_STRING, CBM_AUTO, szDefaultFormat );
AppendMenu ( hDispMenu, MF_SEPARATOR, 0, 0 );
for (fmt=0, cFmt=1; cFmt <= cCBCount; cFmt++)
{
wFlags = 0;
fmt = VEnumClipboardFormats( GETMDIINFO(hwndMDI)->pVClpbrd, fmt );
// don't show preview format in menu...
if ( fmt != cf_preview )
{
switch (fmt)
{
case CF_TEXT:
case CF_OEMTEXT:
case CF_DSPTEXT:
case CF_UNICODETEXT:
case CF_DSPBITMAP:
case CF_DIB:
case CF_BITMAP:
case CF_METAFILEPICT:
case CF_DSPMETAFILEPICT:
case CF_ENHMETAFILE:
case CF_DSPENHMETAFILE:
case CF_OWNERDISPLAY:
case CF_PALETTE:
case CF_HDROP:
case CF_LOCALE:
/* can display all of these, put them on menu */
// Check if the current format is the one selected by the user
if (GETMDIINFO(hwndMDI)->CurSelFormat == fmt)
{
bAutoSelect = FALSE;
wFlags |= MF_CHECKED;
}
GetClipboardMenuName(fmt, szName, sizeof(szName));
AppendMenu (hDispMenu, wFlags, fmt, (LPTSTR)szName);
break;
default: /* all the rest... later */
break;
}
}
}
for (fmt=VEnumClipboardFormats (GETMDIINFO(hwndMDI)->pVClpbrd, 0);
fmt;
fmt=VEnumClipboardFormats (GETMDIINFO(hwndMDI)->pVClpbrd, fmt))
if ( fmt != cf_preview )
switch (fmt)
{
case CF_TEXT:
case CF_OEMTEXT:
case CF_DSPTEXT:
case CF_UNICODETEXT:
case CF_DSPBITMAP:
case CF_DIB:
case CF_BITMAP:
case CF_METAFILEPICT:
case CF_DSPMETAFILEPICT:
case CF_ENHMETAFILE:
case CF_DSPENHMETAFILE:
case CF_OWNERDISPLAY:
case CF_PALETTE:
case CF_HDROP:
case CF_LOCALE:
break;
default:
/* can't display this, put it on menu and gray it */
GetClipboardName(fmt, szName, sizeof(szName));
AppendMenu (hDispMenu, MF_GRAYED, fmt, (LPTSTR)szName);
// NTRAID#DB-344956-2001/04/14-mdesai : add support for V5 bitmaps requires new strings, help changes, code to convert, etc
// clipbrd was adding an empty string for this format; now we ignore the format
case CF_DIBV5:
break;
}
VCloseClipboard( GETMDIINFO(hwndMDI)->pVClpbrd );
if (bAutoSelect)
{
GETMDIINFO(hwndMDI)->CurSelFormat = CBM_AUTO;
CheckMenuItem(hDispMenu, CBM_AUTO, MF_BYCOMMAND | MF_CHECKED);
}
}
else
{
PERROR(TEXT("UpdateCBMenu:couldn't open clip, or no data on clip\r\n"));
}
DrawMenuBar(hwnd);
}
/*
* ClearClipboard
*
* This is called to clear the clipboard. If the clipboard is not
* empty the user is asked if it should be cleared.
*/
BOOL ClearClipboard (
register HWND hwnd)
{
register int RetVal;
if (CountClipboardFormats() <= 0)
return(TRUE);
if ( MessageBoxID( hInst, hwnd, IDS_CONFIRMCLEAR, IDS_CLEARTITLE,
MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
{
if (RetVal = SyncOpenClipboard(hwnd))
{
// PINFO("ClearClipboard: emptied clipboard\r\n");
RetVal &= EmptyClipboard();
RetVal &= SyncCloseClipboard();
}
else
{
// PERROR("ClearClipboard: could not open\r\n");
MessageBoxID (hInst,
hwnd,
IDS_CLEAR,
IDS_ERROR,
MB_OK | MB_SYSTEMMODAL | MB_ICONHAND);
}
InvalidateRect(hwnd, NULL, TRUE);
return RetVal;
}
return(FALSE);
}