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.
 
 
 
 
 
 

1503 lines
37 KiB

/******************************Module*Header*******************************\
* Module Name: region.c
*
* Client region support
*
* Created: 15-Jun-1995
* Author: Mark Enstrom [marke]
*
* Copyright (c) 1995-1999 Microsoft Corporation
\**************************************************************************/
#include "precomp.h"
void OrderRects(LPRECT lpR, int nRects)
{
RECT R;
int i,j;
//Sort Left to right
for (i=0; i<nRects; i++){
for (j=i+1; (j<nRects) && ((lpR+j)->top == (lpR+i)->top); j++){
if (((lpR+j)->left < (lpR+i)->left)) {
R = *(lpR+i);
*(lpR+i) = *(lpR+j);
*(lpR+j) = R;
}
}
}
}
/******************************Public*Routine******************************\
* MirrorRgnByWidth
* Mirror a region (hrgn) according a specific width (cx)
* hrgn : region to get mirrored.
* cx : width used to mirror the region.
* phrgn : If it is not NULL the hrgn will not be touched and the new mirrored
region will be returned in phrgn
* But if it is NULL the mirrored region will be copied to hrgn.
*
* WORRNING:
* if phrng is not NULL it is the caller responsibility to free *phrgn latter.
*
* returns:
* TRUE : if the region get mirrored
* FALSE : otherwise.
* See the comment about phrng.
*
\**************************************************************************/
BOOL MirrorRgnByWidth(HRGN hrgn, int cx, HRGN *phrgn)
{
int nRects, i, nDataSize;
HRGN hrgn2 = NULL;
RECT *lpR;
int Saveleft;
RGNDATA *lpRgnData;
BOOL bRet = FALSE;
nDataSize = GetRegionData(hrgn, 0, NULL);
if (nDataSize && (lpRgnData = (RGNDATA *)LocalAlloc(0, nDataSize * sizeof(DWORD)))) {
if (GetRegionData(hrgn, nDataSize, lpRgnData)) {
nRects = lpRgnData->rdh.nCount;
lpR = (RECT *)lpRgnData->Buffer;
Saveleft = lpRgnData->rdh.rcBound.left;
lpRgnData->rdh.rcBound.left = cx - lpRgnData->rdh.rcBound.right;
lpRgnData->rdh.rcBound.right = cx - Saveleft;
for (i=0; i<nRects; i++){
Saveleft = lpR->left;
lpR->left = cx - lpR->right;
lpR->right = cx - Saveleft;
lpR++;
}
OrderRects((RECT *)lpRgnData->Buffer, nRects);
hrgn2 = ExtCreateRegion(NULL, nDataSize, lpRgnData);
if (hrgn2) {
if (phrgn == NULL) {
CombineRgn(hrgn, hrgn2, NULL, RGN_COPY);
DeleteObject((HGDIOBJ)hrgn2);
} else {
*phrgn = hrgn2;
}
bRet = TRUE;
}
}
//Free mem.
LocalFree(lpRgnData);
}
return bRet;
}
BOOL
WINAPI
MirrorRgn(HWND hwnd, HRGN hrgn)
{
RECT rc;
GetWindowRect(hwnd, &rc);
rc.right -= rc.left;
return MirrorRgnByWidth(hrgn, rc.right, NULL);
}
BOOL
MirrorRgnDC(HDC hdc, HRGN hrgn, HRGN *phrgn)
{
FIXUP_HANDLE(hdc);
if(!IS_ALTDC_TYPE(hdc))
{
PDC_ATTR pdcattr;
PSHARED_GET_VALIDATE((PVOID)pdcattr,hdc,DC_TYPE);
if (pdcattr) {
return MirrorRgnByWidth(hrgn, NtGdiGetDeviceWidth(hdc), phrgn);
}
}
return FALSE;
}
/******************************Public*Routine******************************\
* iRectRelation
*
* returns:
* CONTAINS where prcl1 contains prcl2
* CONTAINED where prcl1 contained by prcl2
* 0 - otherwise
*
* History:
* 19-Nov-1993 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
int
iRectRelation(
PRECTL prcl1,
PRECTL prcl2
)
{
int iRet = 0;
if ((prcl1->left <= prcl2->left) &&
(prcl1->right >= prcl2->right) &&
(prcl1->top <= prcl2->top) &&
(prcl1->bottom >= prcl2->bottom))
{
iRet = CONTAINS;
}
else if (
(prcl2->left <= prcl1->left) &&
(prcl2->right >= prcl1->right) &&
(prcl2->top <= prcl1->top) &&
(prcl2->bottom >= prcl1->bottom))
{
iRet = CONTAINED;
}
else if (
(prcl1->left >= prcl2->right) ||
(prcl1->right <= prcl2->left) ||
(prcl1->top >= prcl2->bottom) ||
(prcl1->bottom <= prcl2->top))
{
iRet = DISJOINT;
}
return(iRet);
}
/******************************Public*Routine******************************\
*
* CreateRectRgn gets an hrgn with user-mode PRGNATTR pointer and
* sets the type to SIMPLEREGION.
*
* Arguments:
*
* x1
* y1
* x2
* y2
*
* Return Value:
*
* HRGN or NULL
*
* History:
*
* 15-Jun-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
#define MIN_REGION_COORD ((LONG) 0xF8000000)
#define MAX_REGION_COORD ((LONG) 0x07FFFFFF)
HRGN
WINAPI
CreateRectRgn(
int x1,
int y1,
int x2,
int y2
)
{
//
// get a region handle, allocate memory for the
// region and associate handle with memory
//
PRGNATTR prRegion;
HRGN hrgn;
//
// rectangle must be ordered
//
#if NOREORDER_RGN
if ((x1 > x2) || (y1 > y2))
{
WARNING("CreateRectRgn called with badly ordered region");
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
}
#else
if (x1 > x2)
{
int t = x1;
x1 = x2;
x2 = t;
}
if (y1 > y2)
{
int t = y1;
y1 = y2;
y2 = t;
}
#endif
//
// make sure ordered coordinates are legal
//
if ((x1 < MIN_REGION_COORD) ||
(y1 < MIN_REGION_COORD) ||
(x2 > MAX_REGION_COORD) ||
(y2 > MAX_REGION_COORD))
{
GdiSetLastError(ERROR_INVALID_PARAMETER);
return((HRGN) 0);
}
//
// get a handle for the new region
//
hrgn = (HRGN)hGetPEBHandle(RegionHandle,0);
if (hrgn == NULL)
{
hrgn = NtGdiCreateRectRgn(0,0,1,1);
}
PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
if (prRegion)
{
if ((x1 == x2) || (y1 == y2))
{
prRegion->Flags = NULLREGION;
prRegion->Rect.left = 0;
prRegion->Rect.top = 0;
prRegion->Rect.right = 0;
prRegion->Rect.bottom = 0;
}
else
{
prRegion->Flags = SIMPLEREGION;
//
// assign region rectangle
//
prRegion->Rect.left = x1;
prRegion->Rect.top = y1;
prRegion->Rect.right = x2;
prRegion->Rect.bottom = y2;
}
//
// mark user-mode region as valid, not cached
//
prRegion->AttrFlags = ATTR_RGN_VALID | ATTR_RGN_DIRTY;
}
else
{
if (hrgn != NULL)
{
WARNING("Shared hrgn handle has no valid PRGNATTR");
DeleteRegion(hrgn);
hrgn = NULL;
}
}
return(hrgn);
}
/******************************Public*Routine******************************\
* CreateRectRgnIndirect *
* *
* Client side stub. *
* *
* Tue 04-Jun-1991 16:58:01 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
HRGN WINAPI CreateRectRgnIndirect(CONST RECT *prcl)
{
return
CreateRectRgn
(
prcl->left,
prcl->top,
prcl->right,
prcl->bottom
);
}
/******************************Public*Routine******************************\
*
* The PtInRegion function determines whether the specified point is
* inside the specified region.
*
* Arguments:
*
* hrgn - app region handle
* x - point x
* y - point y
*
* Return Value:
*
* If the specified point is in the region, the return value is TRUE.
* If the function fails, the return value is FALSE.
*
* History:
*
* 21-Jun-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
WINAPI
PtInRegion(
HRGN hrgn,
int x,
int y
)
{
BOOL bRet = FALSE;
BOOL bUserMode = FALSE;
PRECTL prcl;
PRGNATTR prRegion;
FIXUP_HANDLE(hrgn);
PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
if (prRegion != NULL)
{
if (prRegion->Flags == NULLREGION)
{
bRet = FALSE;
bUserMode = TRUE;
}
else if (prRegion->Flags == SIMPLEREGION)
{
prcl = &prRegion->Rect;
if ((x >= prcl->left) && (x < prcl->right) &&
(y >= prcl->top) && (y < prcl->bottom))
{
bRet = TRUE;
}
bUserMode = TRUE;
}
}
if (!bUserMode)
{
bRet = NtGdiPtInRegion(hrgn,x,y);
}
return(bRet);
}
/******************************Public*Routine******************************\
*
* The RectInRegion function determines whether any part of the specified
* rectangle is within the boundaries of a region.
*
* Arguments:
*
* hrgn - app region handle
* prcl - app rectangle
*
* Return Value:
*
* If any part of the specified rectangle lies within the boundaries
* of the region, the return value is TRUE.
*
* If the function fails, the return value is FALSE.
*
* History:
*
* 21-Jun-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
WINAPI
RectInRegion(
HRGN hrgn,
CONST RECT *prcl
)
{
PRGNATTR prRegion;
BOOL bRet = FALSE;
RECTL TempRect;
LONG iRelation;
BOOL bUserMode = FALSE;
FIXUP_HANDLE(hrgn);
PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
if (prRegion != NULL)
{
if (prRegion->Flags == NULLREGION)
{
bRet = FALSE;
bUserMode = TRUE;
}
else if (prRegion->Flags == SIMPLEREGION)
{
TempRect = *((PRECTL)prcl);
ORDER_PRECTL((&TempRect));
iRelation = iRectRelation(&prRegion->Rect,&TempRect);
if (iRelation != DISJOINT)
{
bRet = TRUE;
}
bUserMode = TRUE;
}
}
if (!bUserMode)
{
bRet = NtGdiRectInRegion(hrgn, (PRECT)prcl);
}
return(bRet);
}
/******************************Public*Routine******************************\
*
* The CombineRgn function combines two regions and stores the result in
* a third region. The two regions are combined according to the specified
* mode.
*
* Arguments:
*
* hrgnDst - destination region
* hrgnSrc1 - source region
* hrgnSrc2 - source region
* iMode - destination region
*
* Return Value:
*
* The resulting type of region or ERROR
*
* History:
*
* 21-Jun-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
int
WINAPI
CombineRgn(
HRGN hrgnDst,
HRGN hrgnSrc1,
HRGN hrgnSrc2,
int iMode
)
{
LONG ResultComplexity = COMPLEXREGION;
int iRet = ERROR;
//
// Check if this operation can be completed in user-mode.
// hrgnDst must have a user mode RGNATTR. hrgnSrc1 must
// also have a user mode RGNATTR. If iMode is not RGN_COPY
// then hrgnSrc2 must have a user mode RGNATTR except for certain
// combinations.
//
PRGNATTR prRegionDst;
PRGNATTR prRegionSrc1;
PRGNATTR prRegionSrc2;
PRECTL prclRes;
PRECTL prclSrc1;
PRECTL prclSrc2;
LONG ComplexSrc1;
LONG ComplexSrc2;
FIXUP_HANDLE(hrgnDst);
FIXUP_HANDLE(hrgnSrc1);
FIXUP_HANDLEZ(hrgnSrc2);
PSHARED_GET_VALIDATE(prRegionDst,hrgnDst,RGN_TYPE);
PSHARED_GET_VALIDATE(prRegionSrc1,hrgnSrc1,RGN_TYPE);
if ((prRegionDst != (PRGNATTR)NULL) &&
(prRegionSrc1 != (PRGNATTR)NULL))
{
//
// region Src1 must me NULL or SIMPLE for current
// user-mode optimizations. If Rect is the region
// bounding box, then it will be possible for
// some combinations with regionC to become
// SIMPLE or NULL.
//
prclSrc1 = &prRegionSrc1->Rect;
ComplexSrc1 = prRegionSrc1->Flags;
if (ComplexSrc1 > SIMPLEREGION)
{
goto CombineRgnKernelMode;
}
if (iMode == RGN_COPY)
{
prclRes = prclSrc1;
ResultComplexity = ComplexSrc1;
}
else
{
LONG iRelation;
//
// validate regionSrc2
//
PSHARED_GET_VALIDATE(prRegionSrc2,hrgnSrc2,RGN_TYPE);
if (
(prRegionSrc2 == (PRGNATTR)NULL) ||
(prRegionSrc2->Flags > SIMPLEREGION)
)
{
goto CombineRgnKernelMode;
}
prclSrc2 = &prRegionSrc2->Rect;
ComplexSrc2 = prRegionSrc2->Flags;
switch (iMode)
{
case RGN_AND:
//
// Creates the intersection of the two
// combined regions.
//
if ((ComplexSrc1 == NULLREGION) ||
(ComplexSrc2 == NULLREGION))
{
//
// intersection with NULL is NULL
//
ResultComplexity = NULLREGION;
}
else
{
iRelation = iRectRelation(prclSrc1,prclSrc2);
if (iRelation == DISJOINT)
{
ResultComplexity = NULLREGION;
}
else if (iRelation == CONTAINED)
{
//
// Src1 is contained in Src2
//
ResultComplexity = SIMPLEREGION;
prclRes = prclSrc1;
}
else if (iRelation == CONTAINS)
{
//
// Src1 is contains Src2
//
ResultComplexity = SIMPLEREGION;
prclRes = prclSrc2;
}
}
break;
case RGN_OR:
case RGN_XOR:
//
// RGN_OR: Creates the union of two combined regions.
// RGN_XOR: Creates the union of two combined regions
// except for any overlapping areas.
//
if (ComplexSrc1 == NULLREGION)
{
if (ComplexSrc2 == NULLREGION)
{
ResultComplexity = NULLREGION;
}
else
{
ResultComplexity = SIMPLEREGION;
prclRes = prclSrc2;
}
}
else if (ComplexSrc2 == NULLREGION)
{
ResultComplexity = SIMPLEREGION;
prclRes = prclSrc1;
}
else if (iMode == RGN_OR)
{
iRelation = iRectRelation(prclSrc1,prclSrc2);
if (iRelation == CONTAINED)
{
//
// Src1 contained in Src2
//
ResultComplexity = SIMPLEREGION;
prclRes = prclSrc2;
}
else if (iRelation == CONTAINS)
{
//
// Src1 contains Src2
//
ResultComplexity = SIMPLEREGION;
prclRes = prclSrc1;
}
}
break;
case RGN_DIFF:
//
// Combines the parts of hrgnSrc1 that are not
// part of hrgnSrc2.
//
if (ComplexSrc1 == NULLREGION)
{
ResultComplexity = NULLREGION;
}
else if (ComplexSrc2 == NULLREGION)
{
ResultComplexity = SIMPLEREGION;
prclRes = prclSrc1;
}
else
{
iRelation = iRectRelation(prclSrc1,prclSrc2);
if (iRelation == DISJOINT)
{
//
// don't intersect so don't subtract anything
//
ResultComplexity = SIMPLEREGION;
prclRes = prclSrc1;
}
else if (iRelation == CONTAINED)
{
ResultComplexity = NULLREGION;
}
}
break;
}
}
//
// try to combine
//
if (ResultComplexity == NULLREGION)
{
if (SetRectRgn(hrgnDst,0,0,0,0))
{
iRet = NULLREGION;
}
}
else if (ResultComplexity == SIMPLEREGION)
{
if (SetRectRgn(hrgnDst,
prclRes->left,
prclRes->top,
prclRes->right,
prclRes->bottom))
{
iRet = SIMPLEREGION;
}
}
}
if (ResultComplexity != COMPLEXREGION)
{
prRegionDst->AttrFlags |= ATTR_RGN_DIRTY;
}
CombineRgnKernelMode:
if (ResultComplexity == COMPLEXREGION)
{
iRet = NtGdiCombineRgn(hrgnDst,hrgnSrc1,hrgnSrc2,iMode);
}
return(iRet);
}
/******************************Public*Routine******************************\
*
* OffsetRgn checks for user-mode region data, if it exits the the
* rectregio is offset, otherwise the kernel is called
*
* Arguments:
*
* hrgn - app region handle
* x - offset in x
* y - offset in y
*
* Return Value:
*
*
*
* History:
*
* 21-Jun-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
int
WINAPI
OffsetRgn(
HRGN hrgn,
int x,
int y
)
{
int iRet;
BOOL bClientRegion = FALSE;
PRGNATTR prRegion;
FIXUP_HANDLE(hrgn);
PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
if (prRegion != NULL)
{
iRet = prRegion->Flags;
if (iRet == NULLREGION)
{
bClientRegion = TRUE;
}
else if (iRet == SIMPLEREGION)
{
RECTL rcl = prRegion->Rect;
bClientRegion = TRUE;
//
// try to offset the region, check for overflow
//
if ( !((rcl.left >= rcl.right) ||
(rcl.top >= rcl.bottom)))
{
rcl.left += x;
rcl.top += y;
rcl.right += x;
rcl.bottom += y;
if (VALID_SCRRC(rcl))
{
prRegion->Rect = rcl;
prRegion->AttrFlags |= ATTR_RGN_DIRTY;
}
else
{
//
// over/underflow
//
iRet = ERROR;
}
}
}
}
if (!bClientRegion)
{
iRet = NtGdiOffsetRgn(hrgn,x,y);
}
return(iRet);
}
/******************************Public*Routine******************************\
*
* GetRgnBox tries to return user-mode rectregion data, otherwies
* make kernel mode transition to get region data.
*
* Arguments:
*
* hrgn - app region handle
* prcl - app rect pointer
*
* Return Value:
*
* region complexity, if the hrgn parameter does not identify a
* valid region, the return value is zero.
*
* History:
*
* 21-Jun-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
int
WINAPI
GetRgnBox(
HRGN hrgn,
LPRECT prcl
)
{
int iRet;
BOOL bClientRegion = FALSE;
//
// check for user-mode region data
//
PRGNATTR prRegion;
FIXUP_HANDLE(hrgn);
PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
if (prRegion != NULL)
{
iRet = prRegion->Flags;
if (iRet == NULLREGION)
{
bClientRegion = TRUE;
prcl->left = 0;
prcl->top = 0;
prcl->right = 0;
prcl->bottom = 0;
}
else if (iRet == SIMPLEREGION)
{
bClientRegion = TRUE;
prcl->left = prRegion->Rect.left;
prcl->top = prRegion->Rect.top;
prcl->right = prRegion->Rect.right;
prcl->bottom = prRegion->Rect.bottom;
}
}
if (!bClientRegion)
{
iRet = NtGdiGetRgnBox(hrgn, prcl);
}
return(iRet);
}
/******************************Public*Routine******************************\
* PtVisible *
* *
* Client side stub. *
* *
* Thu 06-Jun-1991 00:58:46 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL
WINAPI
PtVisible(
HDC hdc,
int x,
int y
)
{
FIXUP_HANDLE(hdc);
return(NtGdiPtVisible(hdc,x,y));
}
/******************************Public*Routine******************************\
* RectVisible *
* *
* Client side stub. *
* *
* Thu 06-Jun-1991 00:58:46 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL
WINAPI
RectVisible(
HDC hdc,
CONST RECT *prcl
)
{
FIXUP_HANDLE(hdc);
return(NtGdiRectVisible(hdc,(LPRECT)prcl));
}
/******************************Public*Routine******************************\
*
* SetRectRgn checks for a user-mode portion of the region. If the
* User-mode data is valid, the region is set to rect locally, otherwise
* a kernel mode call is made to set the region
*
* Arguments:
*
* hrgn - app region handle
* x1,y1,x2,y2 - app region data
*
* Return Value:
*
* BOOL status
*
\**************************************************************************/
BOOL
WINAPI
SetRectRgn(
HRGN hrgn,
int x1,
int y1,
int x2,
int y2
)
{
BOOL bStatus;
PRGNATTR prRegion;
//
// if hrgn has a user-mode rectregion, then set
//
FIXUP_HANDLE(hrgn);
PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
if (prRegion != NULL)
{
PRECTL prcl = &prRegion->Rect;
if ((x1 == x2) || (y1 == y2))
{
prRegion->Flags = NULLREGION;
prcl->left = 0;
prcl->top = 0;
prcl->right = 0;
prcl->bottom = 0;
}
else
{
//
// assign and order rectangle
//
prcl->left = x1;
prcl->top = y1;
prcl->right = x2;
prcl->bottom = y2;
ORDER_PRECTL(prcl);
//
// set region flag
//
prRegion->Flags = SIMPLEREGION;
}
prRegion->AttrFlags |= ATTR_RGN_DIRTY;
bStatus = TRUE;
}
else
{
bStatus = NtGdiSetRectRgn(hrgn,x1,y1,x2,y2);
}
return(bStatus);
}
/******************************Public*Routine******************************\
* GetRandomRgn
*
* Client side stub.
*
* 10-Mar-1992 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
int APIENTRY GetRandomRgn(HDC hdc,HRGN hrgn,int iNum)
{
FIXUP_HANDLE(hdc);
FIXUP_HANDLE(hrgn);
return(NtGdiGetRandomRgn(hdc,hrgn,iNum));
}
/******************************Public*Routine******************************\
* GetClipRgn *
* *
* Client side stub. *
* *
* Sat 08-Jun-1991 17:38:18 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
int WINAPI GetClipRgn(HDC hdc,HRGN hrgn)
{
BOOL bRet;
FIXUP_HANDLE(hdc);
FIXUP_HANDLE(hrgn);
bRet = NtGdiGetRandomRgn(hdc, hrgn, 1);
if (hrgn && MIRRORED_HDC(hdc)) {
MirrorRgnDC(hdc, hrgn, NULL);
}
return(bRet);
}
/******************************Public*Routine******************************\
* GetRegionData
*
* Download a region from the server
*
* History:
* 29-Oct-1991 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
DWORD
WINAPI
GetRegionData(
HRGN hrgn,
DWORD nCount,
LPRGNDATA lpRgnData
)
{
DWORD iRet;
FIXUP_HANDLE(hrgn);
//
// If this is just an inquiry, pass over dummy parameters.
//
if (lpRgnData == (LPRGNDATA) NULL)
{
nCount = 0;
}
return(NtGdiGetRegionData(hrgn,nCount,lpRgnData));
}
/******************************Public*Routine******************************\
*
* Try to cache regions with user-mode rectregion defined
*
* Arguments:
*
* h - region handle
*
* Return Value:
*
* BOOL
*
* History:
*
* 21-Jun-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
DeleteRegion(
HRGN hRgn
)
{
PRGNATTR pRgnattr = NULL;
BOOL bRet = FALSE;
BEGIN_BATCH(BatchTypeDeleteRegion,BATCHDELETEREGION);
PSHARED_GET_VALIDATE(pRgnattr,hRgn,RGN_TYPE);
if (pRgnattr)
{
pBatch->hregion = hRgn;
bRet = TRUE;
}
else
{
goto UNBATCHED_COMMAND;
}
COMPLETE_BATCH_COMMAND();
UNBATCHED_COMMAND:
//
// All other cases
//
if (!bRet)
{
bRet = NtGdiDeleteObjectApp(hRgn);
}
return(bRet);
}
/******************************Public*Routine******************************\
* SelectClipRgn
*
* Client side stub.
*
* History:
* 01-Nov-1991 12:53:47 -by- Donald Sidoroff [donalds]
* Now just call ExtSelectClipRgn
\**************************************************************************/
int META WINAPI SelectClipRgn(HDC hdc,HRGN hrgn)
{
return(ExtSelectClipRgn(hdc, hrgn, RGN_COPY));
}
/******************************Public*Routine******************************\
*
* The ExtSelectClipRgn function combines the specified region with the
* current clipping region by using the specified mode.
*
* Arguments:
*
* hdc - app DC handle
* hrgn - app region handle
* iMode - Select mode
*
* Return Value:
*
* If the function succeeds, the return value specifies the new clipping
* region's complexity and can be any one of the following values:
*
* Value Meaning
* NULLREGION Region is empty.
* SIMPLEREGION Region is a single rectangle.
* COMPLEXREGION Region is more than one rectangle.
* ERROR An error occurred
*
* History:
*
* 21-Jun-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
int
META
WINAPI
ExtSelectClipRgn(
HDC hdc,
HRGN hrgn,
int iMode
)
{
int iRet = RGN_ERROR;
HRGN hrgnMirror = NULL;
FIXUP_HANDLE(hdc);
FIXUP_HANDLEZ(hrgn);
//
// Check Metafile
//
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
{
return(MF16_SelectClipRgn(hdc,hrgn,iMode));
}
DC_PLDC(hdc,pldc,iRet);
if (pldc->iType == LO_METADC)
{
if (!MF_ExtSelectClipRgn(hdc,hrgn,iMode))
{
return(iRet);
}
}
}
//
// Attempt to batch ExtSelectClipRgn:
//
// The DC_ATTR structure has a copy of the current vis region
// bounding rectangle, and the handle table has a flag indicating
// whether this region is valid.
//
// Calls can be batched when the iMode is RGN_COPY and either
// hrgn is NULL, or hrgn complexity is SIMPLE. (and the DC is not
// a DIBSECTION DC)
//
//
// FUTURE PERF:
//
// A check is made to determine if the region being selected
// is the same as the last selected region. In this case, only the
// correct return value needs to be calculated, no region changes
// are needed.
//
//
if (hrgn && MIRRORED_HDC(hdc)) {
if (MirrorRgnDC(hdc, hrgn, &hrgnMirror) && hrgnMirror) {
hrgn = hrgnMirror;
}
}
if (iMode == RGN_COPY)
{
//
// validate DC
//
BOOL bBatch = FALSE;
PRGNATTR prRegion = NULL;
PDC_ATTR pdca;
PENTRY pDCEntry;
PSHARED_GET_VALIDATE(pdca,hdc,DC_TYPE);
//
// check if call can be batched. DC must be valid,non-dibsection
// DC and there must be room on the batch and same batch DC
//
BEGIN_BATCH_HDC(hdc,pdca,BatchTypeSelectClip,BATCHSELECTCLIP);
pDCEntry = &pGdiSharedHandleTable[HANDLE_TO_INDEX(hdc)];
ASSERTGDI(pDCEntry,"pDCEntry must be valid when pdcattr is valid");
if (hrgn == NULL)
{
//
// deleting the clip region, so the return complexity
// will be the vis rgn complexity. Just batch the call.
//
if (!(pDCEntry->Flags & HMGR_ENTRY_INVALID_VIS))
{
bBatch = TRUE;
iRet = pdca->VisRectRegion.Flags;
}
}
else
{
PSHARED_GET_VALIDATE(prRegion,hrgn,RGN_TYPE);
//
// pDCEntry must be valid because pdcattr is valid.
// In order to batch, the user-mode RectRegion must
// be valid and the complexity must be simple
//
if (
(prRegion) &&
(prRegion->Flags == SIMPLEREGION) &&
(!(prRegion->AttrFlags & ATTR_CACHED))
&&
!(pDCEntry->Flags & HMGR_ENTRY_INVALID_VIS)
)
{
//
// Batch the call.
//
bBatch = TRUE;
//
// if the new clip region intersects the DC vis region, the
// return value is SIMPLEREGION, otherwise it is NULLREGION
//
iRet = SIMPLEREGION;
if (
(pdca->VisRectRegion.Rect.left >= prRegion->Rect.right) ||
(pdca->VisRectRegion.Rect.top >= prRegion->Rect.bottom) ||
(pdca->VisRectRegion.Rect.right <= prRegion->Rect.left) ||
(pdca->VisRectRegion.Rect.bottom <= prRegion->Rect.top)
)
{
iRet = NULLREGION;
}
}
}
//
// if the call is to be batched, add to the batch
// and return
//
if (!bBatch)
{
goto UNBATCHED_COMMAND;
}
if (hrgn == NULL)
{
iMode |= REGION_NULL_HRGN;
}
else
{
pBatch->rclClip.left = prRegion->Rect.left;
pBatch->rclClip.top = prRegion->Rect.top;
pBatch->rclClip.right = prRegion->Rect.right;
pBatch->rclClip.bottom = prRegion->Rect.bottom;
}
pBatch->iMode = iMode;
COMPLETE_BATCH_COMMAND();
goto BATCHED_COMMAND;
}
//
// call kernel on fall-through and error cases
//
UNBATCHED_COMMAND:
iRet = NtGdiExtSelectClipRgn(hdc,hrgn,iMode);
BATCHED_COMMAND:
if (hrgnMirror) {
DeleteObject((HGDIOBJ)hrgnMirror);
}
return(iRet);
}
/******************************Public*Routine******************************\
* ExcludeClipRect *
* *
* Client side stub. *
* *
* History: *
* Thu 06-Jun-1991 23:10:01 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
int
META WINAPI
ExcludeClipRect(
HDC hdc,
int x1,
int y1,
int x2,
int y2
)
{
int iRet = RGN_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_RecordParms5(hdc,x1,y1,x2,y2,META_EXCLUDECLIPRECT));
DC_PLDC(hdc,pldc,iRet);
if (pldc->iType == LO_METADC)
{
if (!MF_AnyClipRect(hdc,x1,y1,x2,y2,EMR_EXCLUDECLIPRECT))
return(iRet);
}
}
return(NtGdiExcludeClipRect(hdc,x1,y1,x2,y2));
}
/******************************Public*Routine******************************\
* IntersectClipRect *
* *
* Client side stub. *
* *
* History: *
* Thu 06-Jun-1991 23:10:01 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
int
META WINAPI
IntersectClipRect(
HDC hdc,
int x1,
int y1,
int x2,
int y2
)
{
int iRet = RGN_ERROR;
FIXUP_HANDLE(hdc);
if (IS_ALTDC_TYPE(hdc))
{
PLDC pldc;
if (IS_METADC16_TYPE(hdc))
return(MF16_RecordParms5(hdc,x1,y1,x2,y2,META_INTERSECTCLIPRECT));
DC_PLDC(hdc,pldc,iRet);
if (pldc->iType == LO_METADC)
{
if (!MF_AnyClipRect(hdc,x1,y1,x2,y2,EMR_INTERSECTCLIPRECT))
return(iRet);
}
}
return(NtGdiIntersectClipRect(hdc,x1,y1,x2,y2));
}