]> git.saurik.com Git - wxWidgets.git/blobdiff - src/os2/region.cpp
use WX_DEFINE_ARRAY_INT for an array of ints (bug 1536482)
[wxWidgets.git] / src / os2 / region.cpp
index b3ff3e34d72f7903b1407761fcdc80d77cc876a9..f2fe44a6077f0c99af27031d6ed8cfdf93f2ab74 100644 (file)
@@ -1,26 +1,29 @@
 /////////////////////////////////////////////////////////////////////////////
-// File:      region.cpp
+// File:      src/os2/region.cpp
 // Purpose:   Region class
 // Author:    David Webster
 // Modified by:
 // Created:   10/15/99
-// RCS-ID:       $Id$
-// Copyright: (c) Davdi Webster
+// RCS-ID:    $Id$
+// Copyright: (c) David Webster
 // Licence:   wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
-#include "wx/app.h"
+#ifndef WX_PRECOMP
+    #include "wx/app.h"
+    #include "wx/window.h"
+    #include "wx/gdicmn.h"
+#endif
+
 #include "wx/os2/region.h"
-#include "wx/gdicmn.h"
 
-#include "wx/window.h"
 #include "wx/os2/private.h"
 
-       IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
-       IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
+IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
+IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
 
 //-----------------------------------------------------------------------------
 // wxRegionRefData implementation
@@ -31,6 +34,7 @@ public:
     wxRegionRefData()
     {
         m_hRegion = 0;
+        m_hPS     = 0;
     }
 
     wxRegionRefData(const wxRegionRefData& rData)
@@ -38,6 +42,7 @@ public:
         RGNRECT                     vRgnData;
         PRECTL                      pRect = NULL;
 
+        vRgnData.ulDirection = RECTDIR_LFRT_TOPBOT;
         if (::GpiQueryRegionRects( rData.m_hPS      // Pres space
                                   ,rData.m_hRegion  // Handle of region to query
                                   ,NULL             // Return all RECTs
@@ -65,7 +70,7 @@ public:
         }
     }
 
-    ~wxRegionRefData()
+    virtual ~wxRegionRefData()
     {
         ::GpiDestroyRegion(m_hPS, m_hRegion);
     }
@@ -75,11 +80,19 @@ public:
 };
 
 #define M_REGION (((wxRegionRefData*)m_refData)->m_hRegion)
+#define M_REGION_OF(rgn) (((wxRegionRefData*)(rgn.m_refData))->m_hRegion)
 
 //-----------------------------------------------------------------------------
 // wxRegion
 //-----------------------------------------------------------------------------
 
+// General remark:
+// wxRegion is always basically stored in wx coordinates. However, since
+// OS/2's internal functions rely on "top > bottom", the values of top and
+// bottom values of a region need to be interchanged, as compared to wx.
+// This needs to be taken into account when feeding any rectangle to wx _or_
+// when accessing the region data via GetBox, wxRegionIterator or otherwise.
+
 /*!
  * Create an empty region.
  */
@@ -89,11 +102,13 @@ wxRegion::wxRegion()
 } // end of wxRegion::wxRegion
 
 wxRegion::wxRegion(
-  WXHRGN                            hRegion
+  WXHRGN                            hRegion,
+  WXHDC                             hPS
 )
 {
     m_refData = new wxRegionRefData;
     M_REGION = (HRGN) hRegion;
+    (((wxRegionRefData*)m_refData)->m_hPS) = hPS;
 } // end of wxRegion::wxRegion
 
 wxRegion::wxRegion(
@@ -154,8 +169,8 @@ wxRegion::wxRegion(
 
     vRect.xLeft   = rTopLeft.x;
     vRect.xRight  = rBottomRight.x;
-    vRect.yBottom = rBottomRight.y;
-    vRect.yTop    = rTopLeft.y;
+    vRect.yBottom = rTopLeft.y;
+    vRect.yTop    = rBottomRight.y;
 
     m_refData     = new wxRegionRefData;
 
@@ -217,176 +232,130 @@ wxRegion::~wxRegion()
 {
 } // end of wxRegion::~wxRegion
 
+wxObjectRefData *wxRegion::CreateData() const
+{
+    return new wxRegionRefData;
+}
+
+wxObjectRefData *wxRegion::CloneData(const wxObjectRefData *data) const
+{
+    return new wxRegionRefData(*(wxRegionRefData *)data);
+}
+
 //-----------------------------------------------------------------------------
 //# Modify region
 //-----------------------------------------------------------------------------
 
-//
-// Clear current region
-//
-void wxRegion::Clear()
+bool wxRegion::DoOffset( wxCoord x, wxCoord y )
 {
-    UnRef();
-} // end of wxRegion::Clear
-
-//
-// Combine rectangle (x, y, w, h) with this.
-//
-bool wxRegion::Combine(
-  wxCoord                           x
-, wxCoord                           y
-, wxCoord                           vWidth
-, wxCoord                           vHeight
-, wxRegionOp                        eOp
-)
-{
-    //
-    // Don't change shared data
-    //
-    if (!m_refData)
+    if ( !x && !y )
     {
-        m_refData = new wxRegionRefData();
+        // nothing to do
+        return true;
     }
-    else if (m_refData->GetRefCount() > 1)
-    {
-        wxRegionRefData*            pRef = (wxRegionRefData*)m_refData;
 
-        UnRef();
-        m_refData = new wxRegionRefData(*pRef);
-    }
+    AllocExclusive();
 
-    //
-    // If ref count is 1, that means it's 'ours' anyway so no action.
-    //
-    RECTL                           vRect;
-
-    vRect.xLeft   = x;
-    vRect.xRight  = x + vWidth;
-    vRect.yBottom = y;
-    vRect.yTop    = y + vHeight;
-
-    HRGN                            hRgn = ::GpiCreateRegion( ((wxRegionRefData*)m_refData)->m_hPS
-                                                             ,1
-                                                             ,&vRect
-                                                            );
-    LONG                            lMode = 0L;
-
-    switch (eOp)
+#if 0
+    if ( ::OffsetRgn(GetHrgn(), x, y) == ERROR )
     {
-        case wxRGN_AND:
-            lMode = CRGN_AND;
-            break;
-
-        case wxRGN_OR:
-            lMode = CRGN_OR;
-            break;
-
-        case wxRGN_XOR:
-            lMode = CRGN_XOR;
-            break;
-
-        case wxRGN_DIFF:
-            lMode = CRGN_DIFF;
-            break;
-
-        case wxRGN_COPY:
-        default:
-            lMode = CRGN_COPY;
-            break;
+        wxLogLastError(_T("OffsetRgn"));
+
+        return false;
     }
-    bool                            bSuccess = ::GpiCombineRegion( ((wxRegionRefData*)m_refData)->m_hPS
-                                                                  ,M_REGION
-                                                                  ,M_REGION
-                                                                  ,hRgn
-                                                                  ,lMode
-                                                                 );
-    ::GpiDestroyRegion ( ((wxRegionRefData*)m_refData)->m_hPS
-                        ,hRgn
-                       );
-
-    return bSuccess;
-} // end of wxRegion::Combine
+#endif
+    return true;
+}
 
 //
-// Union region with this.
+// Clear current region
 //
-bool wxRegion::Combine(
-  const wxRegion&                   rRegion
-, wxRegionOp                        eOp
-)
+void wxRegion::Clear()
 {
-    if (rRegion.Empty())
-        return FALSE;
+    UnRef();
+} // end of wxRegion::Clear
 
+//
+// Union region with this.
+//
+bool wxRegion::DoCombine( const wxRegion& rRegion, wxRegionOp eOp )
+{
     //
-    // Don't change shared data
+    // We can't use the API functions if we don't have a valid region handle
     //
     if (!m_refData)
     {
-        m_refData = new wxRegionRefData();
+        // combining with an empty/invalid region works differently depending
+        // on the operation
+        switch (eOp)
+        {
+            case wxRGN_COPY:
+            case wxRGN_OR:
+            case wxRGN_XOR:
+                *this = rRegion;
+                break;
+
+            default:
+                wxFAIL_MSG( _T("unknown region operation") );
+                // fall through
+
+            case wxRGN_AND:
+            case wxRGN_DIFF:
+                // leave empty/invalid
+                return false;
+        }
     }
-    else  if (m_refData->GetRefCount() > 1)
+    else // we have a valid region
     {
-        wxRegionRefData*            pRef = (wxRegionRefData*)m_refData;
 
-        UnRef();
-        m_refData = new wxRegionRefData(*pRef);
-    }
-
-    LONG                            lMode = 0;
+        LONG                        lMode = 0;
 
-    switch (eOp)
-    {
-        case wxRGN_AND:
-            lMode = CRGN_AND;
-            break;
-
-        case wxRGN_OR:
-            lMode = CRGN_OR;
-            break;
-
-        case wxRGN_XOR:
-            lMode = CRGN_XOR;
-            break;
-
-        case wxRGN_DIFF:
-            lMode = CRGN_DIFF;
-            break;
-
-        case wxRGN_COPY:
-        default:
-            lMode = CRGN_COPY;
-            break;
+        switch (eOp)
+        {
+            case wxRGN_AND:
+                lMode = CRGN_AND;
+                break;
+
+            case wxRGN_OR:
+                lMode = CRGN_OR;
+                break;
+
+            case wxRGN_XOR:
+                lMode = CRGN_XOR;
+                break;
+
+            case wxRGN_DIFF:
+                lMode = CRGN_DIFF;
+                break;
+
+            case wxRGN_COPY:
+            default:
+                lMode = CRGN_COPY;
+                break;
+        }
+        return (::GpiCombineRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
+                                   ,M_REGION
+                                   ,M_REGION
+                                   ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion
+                                   ,lMode
+                                  ) != RGN_ERROR);
     }
-    return (::GpiCombineRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
-                               ,M_REGION
-                               ,M_REGION
-                               ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion
-                               ,lMode
-                              ) != RGN_ERROR);
-} // end of wxRegion::Combine
-
-bool wxRegion::Combine(
-  const wxRect&                     rRect
-, wxRegionOp                        eOp
-)
-{
-    return Combine( rRect.GetLeft()
-                   ,rRect.GetTop()
-                   ,rRect.GetWidth()
-                   ,rRect.GetHeight()
-                   ,eOp
-                  );
+    return true;
 } // end of wxRegion::Combine
 
 //-----------------------------------------------------------------------------
 //# Information on region
 //-----------------------------------------------------------------------------
 
+bool wxRegion::DoIsEqual(const wxRegion& WXUNUSED(region)) const
+{
+    return false;
+}
+
 //
 // Outer bounds of region
 //
-void wxRegion::GetBox(
+bool wxRegion::DoGetBox(
   wxCoord&                          x
 , wxCoord&                          y
 , wxCoord&                          vWidth
@@ -396,41 +365,37 @@ void wxRegion::GetBox(
     if (m_refData)
     {
         RECTL                       vRect;
+        APIRET                      rc;
 
-        ::GpiQueryRegionBox( ((wxRegionRefData*)m_refData)->m_hPS
+        rc = ::GpiQueryRegionBox( ((wxRegionRefData*)m_refData)->m_hPS
                             ,M_REGION
                             ,&vRect
                            );
         x       = vRect.xLeft;
-        y       = vRect.yTop;
+        y       = vRect.yBottom;
         vWidth  = vRect.xRight - vRect.xLeft;
         vHeight = vRect.yTop - vRect.yBottom;
+        return true;
     }
     else
     {
         x = y = vWidth = vHeight = 0L;
+        return false;
     }
 } // end of wxRegion::GetBox
 
-wxRect wxRegion::GetBox() const
-{
-    wxCoord x, y, w, h;
-    GetBox(x, y, w, h);
-    return wxRect(x, y, w, h);
-}
-
 //
 // Is region empty?
 //
-bool wxRegion::Empty() const
+bool wxRegion::IsEmpty() const
 {
-    wxCoord                         x;
-    wxCoord                         y;
-    wxCoord                         vWidth;
-    wxCoord                         vHeight;
+    wxCoord x;
+    wxCoord y;
+    wxCoord vWidth;
+    wxCoord vHeight;
 
     if (M_REGION == 0)
-        return TRUE;
+        return true;
 
     GetBox( x
            ,y
@@ -438,53 +403,25 @@ bool wxRegion::Empty() const
            ,vHeight
           );
     return ((vWidth == 0) && (vHeight == 0));
-} // end of wxRegion::Empty
+} // end of wxRegion::IsEmpty
 
 //-----------------------------------------------------------------------------
 // Tests
 //-----------------------------------------------------------------------------
-
-//
-// Does the region contain the point (x,y)?
-wxRegionContain wxRegion::Contains(
-  wxCoord                           x
-, wxCoord                           y
-) const
-{
-    bool                            bOK = FALSE;
-    POINTL                          vPoint;
-
-    vPoint.x = x;
-    vPoint.y = y;
-
-    if (!m_refData)
-        return wxOutRegion;
-
-    LONG                            lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS
-                                                              ,M_REGION
-                                                              ,&vPoint
-                                                             );
-    if (lInside == PRGN_INSIDE)
-        return wxInRegion;
-    return wxOutRegion;
-} // end of wxRegion::Contains
-
 //
 // Does the region contain the point pt?
 //
-wxRegionContain wxRegion::Contains(
-  const wxPoint&                    rPoint
-) const
+wxRegionContain wxRegion::DoContainsPoint( wxCoord x, wxCoord y ) const
 {
-    POINTL                          vPoint = { rPoint.x, rPoint.y };
+    POINTL vPoint = { x, y };
 
     if (!m_refData)
         return wxOutRegion;
 
-    LONG                            lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS
-                                                              ,M_REGION
-                                                              ,&vPoint
-                                                             );
+    LONG lInside = ::GpiPtInRegion( ((wxRegionRefData*)m_refData)->m_hPS,
+                                    M_REGION,
+                                    &vPoint
+                                  );
     if (lInside == PRGN_INSIDE)
         return wxInRegion;
     else
@@ -494,56 +431,29 @@ wxRegionContain wxRegion::Contains(
 //
 // Does the region contain the rectangle (x, y, w, h)?
 //
-wxRegionContain wxRegion::Contains(
-  wxCoord                           x
-, wxCoord                           y
-, wxCoord                           vWidth
-, wxCoord                           vHeight
-) const
+wxRegionContain wxRegion::DoContainsRect(const wxRect& rect) const
 {
-    RECTL                           vRect;
-
     if (!m_refData)
         return wxOutRegion;
 
-    vRect.xLeft   = x;
-    vRect.yTop    = y;
-    vRect.xRight  = x + vWidth;
-    vRect.yBottom = y + vHeight;
-
-    if (PRGN_INSIDE == ::GpiRectInRegion( ((wxRegionRefData*)m_refData)->m_hPS
-                                         ,M_REGION
-                                         ,&vRect
-                                        ))
-        return wxInRegion;
-    else
-        return wxOutRegion;
-} // end of wxRegion::Contains
-
-//
-// Does the region contain the rectangle rect
-//
-wxRegionContain wxRegion::Contains(
-  const wxRect&                     rRect
-) const
-{
-    if (!m_refData)
-        return wxOutRegion;
+    RECTL   vRect;
+    vRect.xLeft   = rect.x;
+    vRect.xRight  = rect.x + rect.width;
+    vRect.yTop    = rect.y + rect.height;
+    vRect.yBottom = rect.y;
+
+    LONG lInside = ::GpiRectInRegion( ((wxRegionRefData*)m_refData)->m_hPS,
+                                      M_REGION,
+                                      &vRect
+                                    );
+    switch (lInside)
+    {
+        case RRGN_INSIDE    :   return wxInRegion;
+        case RRGN_PARTIAL   :   return wxPartRegion;
+        case RRGN_ERROR     :
+        default             :   return wxOutRegion;
+    }
 
-    wxCoord                         x;
-    wxCoord                         y;
-    wxCoord                         vWidth;
-    wxCoord                         vHeight;
-
-    x       = rRect.x;
-    y       = rRect.y;
-    vWidth  = rRect.GetWidth();
-    vHeight = rRect.GetHeight();
-    return Contains( x
-                    ,y
-                    ,vWidth
-                    ,vHeight
-                   );
 } // end of wxRegion::Contains
 
 //
@@ -567,6 +477,7 @@ void wxRegion::SetPS(
     RGNRECT                     vRgnData;
     PRECTL                      pRect = NULL;
 
+    vRgnData.ulDirection = RECTDIR_LFRT_TOPBOT;
     if (::GpiQueryRegionRects( ((wxRegionRefData*)m_refData)->m_hPS
                               ,((wxRegionRefData*)m_refData)->m_hRegion
                               ,NULL
@@ -642,6 +553,7 @@ void wxRegionIterator::Reset(
 )
 {
     m_lCurrent = 0;
+    m_lNumRects = 0;
     m_vRegion  = rRegion;
 
     if (m_pRects)
@@ -656,6 +568,7 @@ void wxRegionIterator::Reset(
         RGNRECT                     vRgnData;
         PRECTL                      pRect;
 
+        vRgnData.ulDirection = RECTDIR_LFRT_TOPBOT;
         if (::GpiQueryRegionRects( ((wxRegionRefData*)rRegion.m_refData)->m_hPS     // Pres space
                                   ,((wxRegionRefData*)rRegion.m_refData)->m_hRegion // Handle of region to query
                                   ,NULL                                             // Return all RECTs
@@ -675,10 +588,12 @@ void wxRegionIterator::Reset(
                                       ,pRect                                            // Will contain the actual RECTS
                                      ))
             {
+#if 0
                 M_REGION = ::GpiCreateRegion( ((wxRegionRefData*)rRegion.m_refData)->m_hPS
                                              ,vRgnData.crcReturned
                                              ,pRect
                                             );
+#endif
                 for( LONG i = 0; i < m_lNumRects; i++)
                 {
                     m_pRects[i].x      = pRect[i].xLeft;
@@ -686,7 +601,9 @@ void wxRegionIterator::Reset(
                     m_pRects[i].y      = pRect[i].yBottom;
                     m_pRects[i].height = pRect[i].yTop - pRect[i].yBottom;
                 }
+#if 0
                 ((wxRegionRefData*)m_refData)->m_hPS = ((wxRegionRefData*)rRegion.m_refData)->m_hPS;
+#endif
             }
         }
     }
@@ -739,4 +656,3 @@ wxCoord wxRegionIterator::GetH() const
         return m_pRects[m_lCurrent].height;
     return 0L;
 } // end of wxRegionIterator::GetH
-