From 24f6a020d5c2e2a63b1b70d20318da6debbd08d6 Mon Sep 17 00:00:00 2001
From: FunkyFr3sh <cc.red.alert.1@googlemail.com>
Date: Tue, 27 Sep 2022 13:56:36 +0200
Subject: [PATCH] #177 support 2 more clipper functions -  GetClipList and
 SetClipList - clipping not supported yet in dd_blt!

---
 inc/IDirectDrawClipper.h             |  1 +
 inc/ddclipper.h                      |  2 +
 src/IDirectDraw/IDirectDrawClipper.c | 16 ++++----
 src/ddclipper.c                      | 59 ++++++++++++++++++++++++++++
 4 files changed, 70 insertions(+), 8 deletions(-)

diff --git a/inc/IDirectDrawClipper.h b/inc/IDirectDrawClipper.h
index a1ae9bc..7e5161f 100644
--- a/inc/IDirectDrawClipper.h
+++ b/inc/IDirectDrawClipper.h
@@ -15,6 +15,7 @@ typedef struct IDirectDrawClipperImpl
 
     ULONG ref;
     HWND hwnd;
+    HRGN region;
 
 } IDirectDrawClipperImpl;
 
diff --git a/inc/ddclipper.h b/inc/ddclipper.h
index 11ecc39..0f5ba55 100644
--- a/inc/ddclipper.h
+++ b/inc/ddclipper.h
@@ -7,7 +7,9 @@
 #include "IDirectDrawClipper.h"
 
 
+HRESULT ddc_GetClipList(IDirectDrawClipperImpl* This, LPRECT lpRect, LPRGNDATA lpClipList, LPDWORD lpdwSiz);
 HRESULT ddc_GetHWnd(IDirectDrawClipperImpl* This, HWND FAR* lphWnd);
+HRESULT ddc_SetClipList(IDirectDrawClipperImpl* This, LPRGNDATA lpClipList, DWORD dwFlags);
 HRESULT ddc_SetHWnd(IDirectDrawClipperImpl* This, DWORD dwFlags, HWND hWnd);
 HRESULT dd_CreateClipper(DWORD dwFlags, IDirectDrawClipperImpl** lplpDDClipper, IUnknown FAR* pUnkOuter);
 
diff --git a/src/IDirectDraw/IDirectDrawClipper.c b/src/IDirectDraw/IDirectDrawClipper.c
index d8d32cf..4265784 100644
--- a/src/IDirectDraw/IDirectDrawClipper.c
+++ b/src/IDirectDraw/IDirectDrawClipper.c
@@ -42,16 +42,16 @@ HRESULT __stdcall IDirectDrawClipper__GetClipList(
     LPDWORD lpdwSiz)
 {
     TRACE(
-        "NOT_IMPLEMENTED -> %s(This=%p, lpRect=%p, lpClipList=%p, lpdwSiz=%p)\n", 
+        "-> %s(This=%p, lpRect=%p, lpClipList=%p, lpdwSiz=%p)\n", 
         __FUNCTION__, 
         This, 
         lpRect, 
         lpClipList, 
         lpdwSiz);
 
-    HRESULT ret = DDERR_NOCLIPLIST;
+    HRESULT ret = ddc_GetClipList(This, lpRect, lpClipList, lpdwSiz);
 
-    TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
+    TRACE("<- %s\n", __FUNCTION__);
     return ret;
 }
 
@@ -65,9 +65,9 @@ HRESULT __stdcall IDirectDrawClipper__GetHWnd(IDirectDrawClipperImpl* This, HWND
 
 HRESULT __stdcall IDirectDrawClipper__Initialize(IDirectDrawClipperImpl* This, LPDIRECTDRAW lpDD, DWORD dwFlags)
 {
-    TRACE("NOT_IMPLEMENTED -> %s(This=%p)\n", __FUNCTION__, This);
+    TRACE("-> %s(This=%p)\n", __FUNCTION__, This);
     HRESULT ret = DD_OK;
-    TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
+    TRACE("<- %s\n", __FUNCTION__);
     return ret;
 }
 
@@ -81,9 +81,9 @@ HRESULT __stdcall IDirectDrawClipper__IsClipListChanged(IDirectDrawClipperImpl*
 
 HRESULT __stdcall IDirectDrawClipper__SetClipList(IDirectDrawClipperImpl* This, LPRGNDATA lpClipList, DWORD dwFlags)
 {
-    TRACE("NOT_IMPLEMENTED -> %s(This=%p, lpClipList=%p, dwFlags=%08X)\n", __FUNCTION__, This, lpClipList, dwFlags);
-    HRESULT ret = DD_OK;
-    TRACE("NOT_IMPLEMENTED <- %s\n", __FUNCTION__);
+    TRACE("-> %s(This=%p, lpClipList=%p, dwFlags=%08X)\n", __FUNCTION__, This, lpClipList, dwFlags);
+    HRESULT ret = ddc_SetClipList(This, lpClipList, dwFlags);
+    TRACE("<- %s\n", __FUNCTION__);
     return ret;
 }
 
diff --git a/src/ddclipper.c b/src/ddclipper.c
index cf80077..1d3bcda 100644
--- a/src/ddclipper.c
+++ b/src/ddclipper.c
@@ -5,6 +5,42 @@
 #include "debug.h"
 
 
+HRESULT ddc_GetClipList(IDirectDrawClipperImpl* This, LPRECT lpRect, LPRGNDATA lpClipList, LPDWORD lpdwSiz)
+{
+    if (!This->region)
+        return DDERR_NOCLIPLIST;
+
+    if (!lpdwSiz)
+        return DDERR_INVALIDPARAMS;
+
+    HRGN region = NULL;
+
+    if (lpRect)
+    {
+        region = CreateRectRgnIndirect(lpRect);
+
+        if (!region)
+            return DDERR_INVALIDPARAMS;
+
+        if (CombineRgn(region, This->region, region, RGN_AND) == ERROR)
+        {
+            DeleteObject(region);
+            return DDERR_GENERIC;
+        }
+    }
+    else
+    {
+        region = This->region;
+    }
+
+    *lpdwSiz = GetRegionData(region, *lpdwSiz, lpClipList);
+
+    if (lpRect)
+        DeleteObject(region);
+
+    return DD_OK;
+}
+
 HRESULT ddc_GetHWnd(IDirectDrawClipperImpl* This, HWND FAR* lphWnd)
 {
     if (!lphWnd)
@@ -15,6 +51,29 @@ HRESULT ddc_GetHWnd(IDirectDrawClipperImpl* This, HWND FAR* lphWnd)
     return DD_OK;
 }
 
+HRESULT ddc_SetClipList(IDirectDrawClipperImpl* This, LPRGNDATA lpClipList, DWORD dwFlags)
+{
+    if (This->hwnd)
+        return DDERR_CLIPPERISUSINGHWND;
+
+    if (This->region)
+        DeleteObject(This->region);
+
+    if (lpClipList)
+    {
+        This->region = ExtCreateRegion(NULL, 0, lpClipList);
+
+        if (!This->region)
+            return DDERR_INVALIDCLIPLIST;
+    }
+    else
+    {
+        This->region = NULL;
+    }
+
+    return DD_OK;
+}
+
 HRESULT ddc_SetHWnd(IDirectDrawClipperImpl* This, DWORD dwFlags, HWND hWnd)
 {
     This->hwnd = hWnd;