From 5230934a95bf9b3112ec2a7e070e8cbb4cea7f55 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Sat, 2 Feb 2002 00:40:45 +0000
Subject: [PATCH] wxDC::SetClippingRegion() in wxMSW works like in wxGTK, i.e.
 combines the given region with the old one (also documented this behaviour as
 the correct one)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@13967 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/changes.txt     |  3 ++
 docs/latex/wx/dc.tex | 16 +++++++--
 include/wx/msw/dc.h  |  3 ++
 src/msw/dc.cpp       | 77 +++++++++++++++++++++++++++-----------------
 4 files changed, 67 insertions(+), 32 deletions(-)

diff --git a/docs/changes.txt b/docs/changes.txt
index 4cdb6bdaad..a25333f67f 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -57,6 +57,9 @@ wxMSW:
   style to avoid it, wxFRAME_FLOAT_ON_PARENT style is now obsolete and has no
   effect
 
+- all overloads of wxDC::SetClippingRegion() combine the given region with the
+  previously selected one instead of replacing it
+
 Unix ports:
 
 - You should use `wx-config --cxxflags` in your makefiles instead of
diff --git a/docs/latex/wx/dc.tex b/docs/latex/wx/dc.tex
index 0dc9eed9a0..f756cd292a 100644
--- a/docs/latex/wx/dc.tex
+++ b/docs/latex/wx/dc.tex
@@ -788,11 +788,21 @@ whether text will be drawn with a background colour or not.
 
 \func{void}{SetClippingRegion}{\param{wxCoord}{ x}, \param{wxCoord}{ y}, \param{wxCoord}{ width}, \param{wxCoord}{ height}}
 
+\func{void}{SetClippingRegion}{\param{const wxPoint\& }{pt}, \param{const wxSize\& }{sz}}
+
+\func{void}{SetClippingRegion}{\param{const wxRect\&}{ rect}}
+
 \func{void}{SetClippingRegion}{\param{const wxRegion\&}{ region}}
 
-Sets the clipping region for the DC. The clipping region is an area
-to which drawing is restricted. Possible uses for the clipping region are for clipping text
-or for speeding up window redraws when only a known area of the screen is damaged.
+Sets the clipping region for this device context to the intersection of the
+given region described by the parameters of this method and the previously set
+clipping region. You should call 
+\helpref{DestroyClippingRegion}{wxdcdestroyclippingregion} if you want to set
+the clipping region exactly to the region specified.
+
+The clipping region is an area to which drawing is restricted. Possible uses
+for the clipping region are for clipping text or for speeding up window redraws
+when only a known area of the screen is damaged.
 
 \wxheading{See also}
 
diff --git a/include/wx/msw/dc.h b/include/wx/msw/dc.h
index 30f79932f5..bdb94b9116 100644
--- a/include/wx/msw/dc.h
+++ b/include/wx/msw/dc.h
@@ -235,6 +235,9 @@ protected:
     // common part of DoDrawText() and DoDrawRotatedText()
     void DrawAnyText(const wxString& text, wxCoord x, wxCoord y);
 
+    // common part of DoSetClippingRegion() and DoSetClippingRegionAsRegion()
+    void SetClippingHrgn(WXHRGN hrgn);
+
     // MSW-specific member variables
     int               m_windowExtX;
     int               m_windowExtY;
diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp
index 406f0f2a1e..c222cbbf4c 100644
--- a/src/msw/dc.cpp
+++ b/src/msw/dc.cpp
@@ -279,7 +279,7 @@ void wxDC::UpdateClipBox()
 #endif
 
     RECT rect;
-    GetClipBox(GetHdc(), &rect);
+    ::GetClipBox(GetHdc(), &rect);
 
     m_clipX1 = (wxCoord) XDEV2LOG(rect.left);
     m_clipY1 = (wxCoord) YDEV2LOG(rect.top);
@@ -287,14 +287,50 @@ void wxDC::UpdateClipBox()
     m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom);
 }
 
-void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
+// common part of DoSetClippingRegion() and DoSetClippingRegionAsRegion()
+void wxDC::SetClippingHrgn(WXHRGN hrgn)
 {
+    wxCHECK_RET( hrgn, wxT("invalid clipping region") );
+
 #ifdef __WXMICROWIN__
-    if (!GetHDC()) return;
-#endif
+    if (!GetHdc()) return;
+#endif // __WXMICROWIN__
+
+    // note that we combine the new clipping region with the existing one: this
+    // is compatible with what the other ports do and is the documented
+    // behaviour now (starting with 2.3.3)
+#ifdef __WIN16__
+    RECT rectClip;
+    if ( !::GetClipBox(GetHdc(), &rectClip) )
+        return;
+
+    HRGN hrgnDest = ::CreateRectRgn(0, 0, 0, 0);
+    HRGN hrgnClipOld = ::CreateRectRgn(rectClip.left, rectClip.top,
+                                       rectClip.right, rectClip.bottom);
+
+    if ( ::CombineRgn(hrgnDest, hrgnClipOld, (HRGN)hrgn, RGN_AND) != ERROR )
+    {
+        ::SelectClipRgn(GetHdc(), hrgnDest);
+    }
+
+    ::DeleteObject(hrgnClipOld);
+    ::DeleteObject(hrgnDest);
+#else // Win32
+    if ( ::ExtSelectClipRgn(GetHdc(), (HRGN)hrgn, RGN_AND) == ERROR )
+    {
+        wxLogLastError(_T("ExtSelectClipRgn"));
+
+        return;
+    }
+#endif // Win16/32
 
     m_clipping = TRUE;
 
+    UpdateClipBox();
+}
+
+void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
+{
     // the region coords are always the device ones, so do the translation
     // manually
     //
@@ -309,33 +345,15 @@ void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
     }
     else
     {
-        if ( ::SelectClipRgn(GetHdc(), hrgn) == ERROR )
-        {
-            wxLogLastError(_T("SelectClipRgn"));
-        }
-        DeleteObject(hrgn);
+        SetClippingHrgn((WXHRGN)hrgn);
 
-        UpdateClipBox();
+        ::DeleteObject(hrgn);
     }
 }
 
 void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
 {
-#ifdef __WXMICROWIN__
-    if (!GetHDC()) return;
-#endif
-
-    wxCHECK_RET( GetHrgnOf(region), wxT("invalid clipping region") );
-
-    m_clipping = TRUE;
-
-#ifdef __WIN16__
-    SelectClipRgn(GetHdc(), GetHrgnOf(region));
-#else // Win32
-    ExtSelectClipRgn(GetHdc(), GetHrgnOf(region), RGN_AND);
-#endif // Win16/32
-
-    UpdateClipBox();
+    SetClippingHrgn(region.GetHRGN());
 }
 
 void wxDC::DestroyClippingRegion()
@@ -347,11 +365,12 @@ void wxDC::DestroyClippingRegion()
     if (m_clipping && m_hDC)
     {
         // TODO: this should restore the previous clipping region,
-        // so that OnPaint processing works correctly, and the update clipping region
-        // doesn't get destroyed after the first DestroyClippingRegion.
+        //       so that OnPaint processing works correctly, and the update
+        //       clipping region doesn't get destroyed after the first
+        //       DestroyClippingRegion.
         HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
-        SelectClipRgn(GetHdc(), rgn);
-        DeleteObject(rgn);
+        ::SelectClipRgn(GetHdc(), rgn);
+        ::DeleteObject(rgn);
     }
 
     m_clipping = FALSE;
-- 
2.50.0

