diff --git a/reactos/win32ss/gdi/ntgdi/cliprgn.c b/reactos/win32ss/gdi/ntgdi/cliprgn.c index 9c962256d5c..09f36e13f03 100644 --- a/reactos/win32ss/gdi/ntgdi/cliprgn.c +++ b/reactos/win32ss/gdi/ntgdi/cliprgn.c @@ -190,55 +190,79 @@ NtGdiGetAppClipBox( return iComplexity; } -int APIENTRY NtGdiExcludeClipRect(HDC hDC, - int LeftRect, - int TopRect, - int RightRect, - int BottomRect) +INT +APIENTRY +NtGdiExcludeClipRect( + _In_ HDC hdc, + _In_ INT xLeft, + _In_ INT yTop, + _In_ INT xRight, + _In_ INT yBottom) { - INT Result; - RECTL Rect; - PREGION prgnNew; - PDC dc = DC_LockDc(hDC); + INT iComplexity; + RECTL rect; + PDC pdc; - if (!dc) + /* Lock the DC */ + pdc = DC_LockDc(hdc); + if (pdc == NULL) { EngSetLastError(ERROR_INVALID_HANDLE); return ERROR; } - Rect.left = LeftRect; - Rect.top = TopRect; - Rect.right = RightRect; - Rect.bottom = BottomRect; + /* Convert coordinates to device space */ + rect.left = xLeft; + rect.top = yTop; + rect.right = xRight; + rect.bottom = yBottom; + RECTL_vMakeWellOrdered(&rect); + IntLPtoDP(pdc, (LPPOINT)&rect, 2); - IntLPtoDP(dc, (LPPOINT)&Rect, 2); - - prgnNew = IntSysCreateRectpRgnIndirect(&Rect); - if (!prgnNew) + /* Check if we already have a clip region */ + if (pdc->dclevel.prgnClip != NULL) { - Result = ERROR; + /* We have a region, subtract the rect */ + iComplexity = REGION_SubtractRectFromRgn(pdc->dclevel.prgnClip, + pdc->dclevel.prgnClip, + &rect); + + /* Emulate Windows behavior */ + if (iComplexity == SIMPLEREGION) + iComplexity = COMPLEXREGION; } else { - if (!dc->dclevel.prgnClip) + /* Check if the rect intersects with the window rect */ + if (RECTL_bIntersectRect(&rect, &rect, &pdc->erclWindow)) { - dc->dclevel.prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0); - IntGdiCombineRgn(dc->dclevel.prgnClip, dc->prgnVis, prgnNew, RGN_DIFF); - Result = SIMPLEREGION; + /* It does. In this case create an empty region */ + pdc->dclevel.prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0); + iComplexity = NULLREGION; } else { - Result = IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, prgnNew, RGN_DIFF); + /* Otherwise, emulate strange Windows behavior... */ + pdc->dclevel.prgnClip = IntSysCreateRectpRgn(0, 0, 1, 1); + iComplexity = COMPLEXREGION; + } + + /* Check if creating the region failed */ + if (pdc->dclevel.prgnClip == NULL) + { + /* Return error code */ + iComplexity = ERROR; } - REGION_Delete(prgnNew); } - if (Result != ERROR) - dc->fs |= DC_FLAG_DIRTY_RAO; - DC_UnlockDc(dc); + /* If we succeeded, mark the RAO region as dirty */ + if (iComplexity != ERROR) + pdc->fs |= DC_FLAG_DIRTY_RAO; - return Result; + /* Unlock the DC */ + DC_UnlockDc(pdc); + + return iComplexity; } INT diff --git a/reactos/win32ss/gdi/ntgdi/region.c b/reactos/win32ss/gdi/ntgdi/region.c index 0c20aff642a..4032c7903dd 100644 --- a/reactos/win32ss/gdi/ntgdi/region.c +++ b/reactos/win32ss/gdi/ntgdi/region.c @@ -1773,6 +1773,23 @@ REGION_UnionRectWithRgn( REGION_UnionRegion(rgn, rgn, ®ion); } +INT +FASTCALL +REGION_SubtractRectFromRgn( + PREGION prgnDest, + PREGION prgnSrc, + const RECTL *prcl) +{ + REGION rgnLocal; + + rgnLocal.Buffer = &rgnLocal.rdh.rcBound; + rgnLocal.rdh.nCount = 1; + rgnLocal.rdh.nRgnSize = sizeof(RECT); + rgnLocal.rdh.rcBound = *prcl; + REGION_SubtractRegion(prgnDest, prgnSrc, &rgnLocal); + return REGION_Complexity(prgnDest); +} + BOOL FASTCALL REGION_CreateSimpleFrameRgn( PROSRGNDATA rgn, diff --git a/reactos/win32ss/gdi/ntgdi/region.h b/reactos/win32ss/gdi/ntgdi/region.h index e735b155fef..73bf85af52e 100644 --- a/reactos/win32ss/gdi/ntgdi/region.h +++ b/reactos/win32ss/gdi/ntgdi/region.h @@ -25,6 +25,7 @@ typedef struct _ROSRGNDATA PROSRGNDATA FASTCALL REGION_AllocRgnWithHandle(INT n); PROSRGNDATA FASTCALL REGION_AllocUserRgnWithHandle(INT n); VOID FASTCALL REGION_UnionRectWithRgn(ROSRGNDATA *rgn, const RECTL *rect); +INT FASTCALL REGION_SubtractRectFromRgn(PREGION prgnDest, PREGION prgnSrc, const RECTL *prcl); INT FASTCALL REGION_GetRgnBox(PROSRGNDATA Rgn, RECTL *pRect); BOOL FASTCALL REGION_RectInRegion(PROSRGNDATA Rgn, const RECTL *rc); BOOL FASTCALL REGION_PtInRegion(PREGION, INT, INT);