Removed dependencies on the internals of the region object.
Do not store the region type in the object, it's trivial to determine
from the rectangle count.
Rewrote a few routines to not depend on internal clipping or region
functions.

diff --git a/dlls/gdi/mfdrv/graphics.c b/dlls/gdi/mfdrv/graphics.c
index c44dbc5..aa27b6b 100644
--- a/dlls/gdi/mfdrv/graphics.c
+++ b/dlls/gdi/mfdrv/graphics.c
@@ -22,7 +22,6 @@
 #include <string.h>
 
 #include "gdi.h"
-#include "region.h"
 #include "mfdrv/metafiledrv.h"
 #include "wine/debug.h"
 
diff --git a/dlls/ttydrv/wnd.c b/dlls/ttydrv/wnd.c
index 949f751..ac65fe7 100644
--- a/dlls/ttydrv/wnd.c
+++ b/dlls/ttydrv/wnd.c
@@ -22,7 +22,6 @@
 
 #include "gdi.h"
 #include "ttydrv.h"
-#include "region.h"
 #include "win.h"
 #include "winpos.h"
 #include "wine/debug.h"
@@ -203,6 +202,7 @@
     WND *pWnd;
     int i;
     HWND *list = WIN_ListChildren( parent );
+    HRGN hrgn = 0;
 
     if (!list) return;
     for (i = 0; list[i]; i++)
@@ -217,15 +217,14 @@
             rect.bottom = pWnd->rectWindow.bottom + y;
             if( IntersectRect( &rect, &rect, lpRect ))
             {
-                if(!REGION_UnionRectWithRgn( hrgnClip, &rect ))
-                {
-                    WIN_ReleaseWndPtr( pWnd );
-                    break;
-                }
+                if (!hrgn) hrgn = CreateRectRgnIndirect( &rect );
+                else SetRectRgn( hrgn, rect.left, rect.top, rect.right, rect.bottom );
+                CombineRgn( hrgnClip, hrgnClip, hrgn, RGN_OR );
             }
         }
         WIN_ReleaseWndPtr( pWnd );
     }
+    if (hrgn) DeleteObject( hrgn );
     HeapFree( GetProcessHeap(), 0, list );
 }
 
diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index dbde92b..06109bc 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -34,7 +34,6 @@
 #include "hook.h"
 #include "win.h"
 #include "winpos.h"
-#include "region.h"
 #include "dce.h"
 #include "cursoricon.h"
 #include "nonclient.h"
diff --git a/dlls/x11drv/xrender.c b/dlls/x11drv/xrender.c
index fe4c877..39b478f 100644
--- a/dlls/x11drv/xrender.c
+++ b/dlls/x11drv/xrender.c
@@ -27,7 +27,6 @@
 #include "winnt.h"
 #include "x11drv.h"
 #include "bitmap.h"
-#include "region.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
 
@@ -563,8 +562,7 @@
     XRenderColor col;
     int idx;
     TEXTMETRICW tm;
-    RGNOBJ *obj;
-    XRectangle *pXrect;
+    RGNDATA *data;
     SIZE sz;
     RECT rc;
     BOOL done_extents = FALSE;
@@ -713,12 +711,9 @@
     if (flags & ETO_CLIPPED)
     {
         SaveVisRgn16( hdc );
-        CLIPPING_IntersectVisRect( dc, rc.left, rc.top, rc.right,
-                                   rc.bottom, FALSE );
+        IntersectVisRect16( dc->hSelf, lprect->left, lprect->top, lprect->right, lprect->bottom );
     }
 
-
-
     if(!physDev->xrender->pict) {
         XRenderPictureAttributes pa;
 	pa.subwindow_mode = IncludeInferiors;
@@ -736,52 +731,14 @@
 	TRACE("using existing pict = %lx dc = %p\n", physDev->xrender->pict, dc);
     }
 
-    obj = (RGNOBJ *) GDI_GetObjPtr(dc->hGCClipRgn, REGION_MAGIC);
-    if (!obj)
+    if ((data = X11DRV_GetRegionData( dc->hGCClipRgn, 0 )))
     {
-        ERR("Rgn is 0. Please report this.\n");
-	return FALSE;
+        wine_tsx11_lock();
+        pXRenderSetPictureClipRectangles( gdi_display, physDev->xrender->pict,
+                                          0, 0, (XRectangle *)data->Buffer, data->rdh.nCount );
+        wine_tsx11_unlock();
+        HeapFree( GetProcessHeap(), 0, data );
     }
-    
-    if (obj->rgn->numRects > 0)
-    {
-        XRectangle *pXr;
-        RECT *pRect = obj->rgn->rects;
-        RECT *pEndRect = obj->rgn->rects + obj->rgn->numRects;
-
-        pXrect = HeapAlloc( GetProcessHeap(), 0, 
-			    sizeof(*pXrect) * obj->rgn->numRects );
-	if(!pXrect)
-	{
-	    WARN("Can't alloc buffer\n");
-	    GDI_ReleaseObj( dc->hGCClipRgn );
-	    return FALSE;
-	}
-
-        for(pXr = pXrect; pRect < pEndRect; pRect++, pXr++)
-        {
-            pXr->x = pRect->left;
-            pXr->y = pRect->top;
-            pXr->width = pRect->right - pRect->left;
-            pXr->height = pRect->bottom - pRect->top;
-	    TRACE("Adding clip rect %d,%d - %d,%d\n", pRect->left, pRect->top,
-		  pRect->right, pRect->bottom);
-        }
-    }
-    else {
-        TRACE("no clip rgn\n");
-        pXrect = NULL;
-    }
-
-    wine_tsx11_lock();
-    pXRenderSetPictureClipRectangles( gdi_display, physDev->xrender->pict,
-                                      0, 0, pXrect, obj->rgn->numRects );
-    wine_tsx11_unlock();
-
-    if(pXrect)
-        HeapFree( GetProcessHeap(), 0, pXrect );
-
-    GDI_ReleaseObj( dc->hGCClipRgn );
 
     if(GetBkMode(hdc) != TRANSPARENT) {
         if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE))) {
diff --git a/graphics/x11drv/clipping.c b/graphics/x11drv/clipping.c
index edd0987..cd74b84 100644
--- a/graphics/x11drv/clipping.c
+++ b/graphics/x11drv/clipping.c
@@ -26,62 +26,100 @@
 
 #include "gdi.h"
 #include "x11drv.h"
-#include "region.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
 
 /***********************************************************************
- *           X11DRV_SetDeviceClipping
- *           Copy RECT32s to a temporary buffer of XRectangles and call
- *           TSXSetClipRectangles().
+ *           X11DRV_GetRegionData
  *
- *           Could write using GetRegionData but this would be slower.
+ * Calls GetRegionData on the given region and converts the rectangle
+ * array to XRectangle format. The returned buffer must be freed by
+ * caller using HeapFree(GetProcessHeap(),...).
+ * If hdc_lptodp is not 0, the rectangles are converted through LPtoDP.
  */
-void X11DRV_SetDeviceClipping( X11DRV_PDEVICE *physDev, HRGN hrgn )
+RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp )
 {
-    XRectangle *pXrect;
+    RGNDATA *data;
+    DWORD size;
+    int i;
+    RECT *rect, tmp;
+    XRectangle *xrect;
 
-    RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(hrgn, REGION_MAGIC);
-    if (!obj)
+    if (!(size = GetRegionData( hrgn, 0, NULL ))) return NULL;
+    if (sizeof(XRectangle) > sizeof(RECT))
     {
-        ERR("Rgn is 0. Please report this.\n");
-	return;
+        /* add extra size for XRectangle array */
+        int count = (size - sizeof(RGNDATAHEADER)) / sizeof(RECT);
+        size += count * (sizeof(XRectangle) - sizeof(RECT));
     }
-    
-    if (obj->rgn->numRects > 0)
+    if (!(data = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
+    if (!GetRegionData( hrgn, size, data ))
     {
-        XRectangle *pXr;
-        RECT *pRect = obj->rgn->rects;
-        RECT *pEndRect = obj->rgn->rects + obj->rgn->numRects;
+        HeapFree( GetProcessHeap(), 0, data );
+        return NULL;
+    }
 
-        pXrect = HeapAlloc( GetProcessHeap(), 0, 
-			    sizeof(*pXrect) * obj->rgn->numRects );
-	if(!pXrect)
-	{
-	    WARN("Can't alloc buffer\n");
-	    GDI_ReleaseObj( hrgn );
-	    return;
-	}
-
-        for(pXr = pXrect; pRect < pEndRect; pRect++, pXr++)
+    rect = (RECT *)data->Buffer;
+    xrect = (XRectangle *)data->Buffer;
+    if (hdc_lptodp)  /* map to device coordinates */
+    {
+        LPtoDP( hdc_lptodp, (POINT *)rect, data->rdh.nCount * 2 );
+        for (i = 0; i < data->rdh.nCount; i++)
         {
-            pXr->x = pRect->left;
-            pXr->y = pRect->top;
-            pXr->width = pRect->right - pRect->left;
-            pXr->height = pRect->bottom - pRect->top;
+            if (rect[i].right < rect[i].left)
+            {
+                INT tmp = rect[i].right;
+                rect[i].right = rect[i].left;
+                rect[i].left = tmp;
+            }
+            if (rect[i].bottom < rect[i].top)
+            {
+                INT tmp = rect[i].bottom;
+                rect[i].bottom = rect[i].top;
+                rect[i].top = tmp;
+            }
+        }
+    }
+
+    if (sizeof(XRectangle) > sizeof(RECT))
+    {
+        /* need to start from the end */
+        for (i = data->rdh.nCount-1; i >=0; i--)
+        {
+            tmp = rect[i];
+            xrect[i].x      = tmp.left;
+            xrect[i].y      = tmp.top;
+            xrect[i].width  = tmp.right - tmp.left;
+            xrect[i].height = tmp.bottom - tmp.top;
         }
     }
     else
-        pXrect = NULL;
+    {
+        for (i = 0; i < data->rdh.nCount; i++)
+        {
+            tmp = rect[i];
+            xrect[i].x      = tmp.left;
+            xrect[i].y      = tmp.top;
+            xrect[i].width  = tmp.right - tmp.left;
+            xrect[i].height = tmp.bottom - tmp.top;
+        }
+    }
+    return data;
+}
 
+
+/***********************************************************************
+ *           X11DRV_SetDeviceClipping
+ */
+void X11DRV_SetDeviceClipping( X11DRV_PDEVICE *physDev, HRGN hrgn )
+{
+    RGNDATA *data;
+
+    if (!(data = X11DRV_GetRegionData( hrgn, 0 ))) return;
     TSXSetClipRectangles( gdi_display, physDev->gc, 0, 0,
-                          pXrect, obj->rgn->numRects, YXBanded );
-
-    if(pXrect)
-        HeapFree( GetProcessHeap(), 0, pXrect );
-
-    GDI_ReleaseObj( hrgn );
+                          (XRectangle *)data->Buffer, data->rdh.nCount, YXBanded );
+    HeapFree( GetProcessHeap(), 0, data );
 }
 
 
diff --git a/graphics/x11drv/graphics.c b/graphics/x11drv/graphics.c
index 7e34689..7ea2e13 100644
--- a/graphics/x11drv/graphics.c
+++ b/graphics/x11drv/graphics.c
@@ -45,7 +45,6 @@
 #include "bitmap.h"
 #include "gdi.h"
 #include "palette.h"
-#include "region.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(graphics);
@@ -940,48 +939,29 @@
 BOOL
 X11DRV_PaintRgn( X11DRV_PDEVICE *physDev, HRGN hrgn )
 {
-    RECT box;
-    HRGN tmpVisRgn, prevVisRgn;
     DC *dc = physDev->dc;
-    HDC hdc = physDev->hdc; /* FIXME: should not mix dc/hdc this way */
 
-    if (!(tmpVisRgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
-
-      /* Transform region into device co-ords */
-    if (  !REGION_LPTODP( hdc, tmpVisRgn, hrgn )
-        || OffsetRgn( tmpVisRgn, dc->DCOrgX, dc->DCOrgY ) == ERROR) {
-        DeleteObject( tmpVisRgn );
-	return FALSE;
-    }
-
-      /* Modify visible region */
-    if (!(prevVisRgn = SaveVisRgn16( hdc ))) {
-        DeleteObject( tmpVisRgn );
-	return FALSE;
-    }
-    CombineRgn( tmpVisRgn, prevVisRgn, tmpVisRgn, RGN_AND );
-    SelectVisRgn16( hdc, tmpVisRgn );
-    DeleteObject( tmpVisRgn );
-
-      /* Fill the region */
-
-    GetRgnBox( dc->hGCClipRgn, &box );
     if (X11DRV_SetupGCForBrush( physDev ))
     {
-	/* Update the pixmap from the DIB section */
-    	X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
+        int i;
+        XRectangle *rect;
+        RGNDATA *data = X11DRV_GetRegionData( hrgn, physDev->hdc );
 
-        TSXFillRectangle( gdi_display, physDev->drawable, physDev->gc,
-		          box.left, box.top,
-		          box.right-box.left, box.bottom-box.top );
-    
-	/* Update the DIBSection from the pixmap */
-    	X11DRV_UnlockDIBSection(physDev, TRUE);
+        if (!data) return FALSE;
+        rect = (XRectangle *)data->Buffer;
+        for (i = 0; i < data->rdh.nCount; i++)
+        {
+            rect[i].x += dc->DCOrgX;
+            rect[i].y += dc->DCOrgY;
+        }
+
+        X11DRV_LockDIBSection(physDev, DIB_Status_GdiMod, FALSE);
+        wine_tsx11_lock();
+        XFillRectangles( gdi_display, physDev->drawable, physDev->gc, rect, data->rdh.nCount );
+        wine_tsx11_unlock();
+        X11DRV_UnlockDIBSection(physDev, TRUE);
+        HeapFree( GetProcessHeap(), 0, data );
     }
-
-      /* Restore the visible region */
-
-    RestoreVisRgn16( hdc );
     return TRUE;
 }
 
diff --git a/graphics/x11drv/text.c b/graphics/x11drv/text.c
index fbf5d96..01de6ad 100644
--- a/graphics/x11drv/text.c
+++ b/graphics/x11drv/text.c
@@ -151,7 +151,10 @@
     {
         SIZE sz;
         if (!X11DRV_GetTextExtentPoint( physDev, wstr, count, &sz ))
-	    return FALSE;
+        {
+            result = FALSE;
+            goto END;
+        }
 	width = INTERNAL_XWSTODS(dc, sz.cx);
     }
     ascent = pfo->lpX11Trans ? pfo->lpX11Trans->ascent : font->ascent;
@@ -206,8 +209,7 @@
     if (flags & ETO_CLIPPED)
     {
         SaveVisRgn16( dc->hSelf );
-        CLIPPING_IntersectVisRect( dc, rect.left, rect.top, rect.right,
-                                   rect.bottom, FALSE );
+        IntersectVisRect16( dc->hSelf, lprect->left, lprect->top, lprect->right, lprect->bottom );
     }
 
       /* Draw the text background if necessary */
@@ -395,9 +397,7 @@
 		   dc->DCOrgX + x + width, dc->DCOrgY + y - lineAscent );
     }
 
-    if (flags & ETO_CLIPPED) 
-        RestoreVisRgn16( dc->hSelf );
-
+    if (flags & ETO_CLIPPED) RestoreVisRgn16( dc->hSelf );
     goto END;
 	    
 FAIL:
diff --git a/include/gdi.h b/include/gdi.h
index 973c780..d7ffe88 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -580,16 +580,7 @@
 extern void DC_InitDC( DC * dc );
 extern void DC_UpdateXforms( DC * dc );
 
-
-#define CLIP_INTERSECT 0x0001
-#define CLIP_EXCLUDE   0x0002
-#define CLIP_KEEPRGN   0x0004
-
 /* objects/clipping.c */
-INT CLIPPING_IntersectClipRect( DC * dc, INT left, INT top,
-                                INT right, INT bottom, UINT flags );
-INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
-                               INT right, INT bottom, BOOL exclude );
 extern void CLIPPING_UpdateGCRegion( DC * dc );
 
 /* objects/enhmetafile.c */
diff --git a/include/region.h b/include/region.h
index e66f9a6..682cb2c 100644
--- a/include/region.h
+++ b/include/region.h
@@ -25,26 +25,11 @@
 #include "windef.h"
 #include "wingdi.h"
 
-typedef struct {
-    INT size;
-    INT numRects;
-    INT type; /* NULL, SIMPLE or COMPLEX */
-    RECT *rects;
-    RECT extents;
-} WINEREGION;
+struct _RGNOBJ;
 
-  /* GDI logical region object */
-typedef struct
-{
-    GDIOBJHDR   header;
-    WINEREGION  *rgn;
-} RGNOBJ;
-
-extern BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj );
-extern BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect );
+extern BOOL REGION_DeleteObject( HRGN hrgn, struct _RGNOBJ * obj );
 extern HRGN REGION_CropRgn( HRGN hDst, HRGN hSrc, const RECT *lpRect, const POINT *lpPt );
 extern BOOL REGION_FrameRgn( HRGN dest, HRGN src, INT x, INT y );
-extern BOOL REGION_LPTODP( HDC hdc, HRGN hDest, HRGN hSrc );
 
 #endif  /* __WINE_REGION_H */
 
diff --git a/include/x11drv.h b/include/x11drv.h
index 4effb5f..b5bd9f4 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -198,6 +198,7 @@
 extern Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc );
 extern Pixmap X11DRV_BITMAP_CreatePixmapFromBitmap( HBITMAP hBmp, HDC hdc );
 
+extern RGNDATA *X11DRV_GetRegionData( HRGN hrgn, HDC hdc_lptodp );
 extern void X11DRV_SetDrawable( HDC hdc, Drawable drawable, int mode, int org_x, int org_y );
 extern void X11DRV_StartGraphicsExposures( HDC hdc );
 extern void X11DRV_EndGraphicsExposures( HDC hdc, HRGN hrgn );
diff --git a/objects/clipping.c b/objects/clipping.c
index 2519bca..0051119 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -23,7 +23,6 @@
 #include "wingdi.h"
 #include "wine/winuser16.h"
 #include "gdi.h"
-#include "region.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(clipping);
@@ -205,54 +204,6 @@
 
 
 /***********************************************************************
- *           CLIPPING_IntersectClipRect
- *
- * Helper function for {Intersect,Exclude}ClipRect, can be called from
- * elsewhere (like ExtTextOut()) to skip redundant metafile update and
- * coordinate conversion.
- */
-INT CLIPPING_IntersectClipRect( DC * dc, INT left, INT top,
-                                  INT right, INT bottom, UINT flags )
-{
-    HRGN newRgn;
-    INT ret;
-
-    left   += dc->DCOrgX;
-    right  += dc->DCOrgX;
-    top    += dc->DCOrgY;
-    bottom += dc->DCOrgY;
-
-    if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) return ERROR;
-    if (!dc->hClipRgn)
-    {
-       if( flags & CLIP_INTERSECT )
-       {
-	   dc->hClipRgn = newRgn;
-	   CLIPPING_UpdateGCRegion( dc );
-           return SIMPLEREGION;
-       }
-       else if( flags & CLIP_EXCLUDE )
-       {
-           dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
-     	   CombineRgn( dc->hClipRgn, dc->hVisRgn, 0, RGN_COPY );
-       }
-       else WARN("No hClipRgn and flags are %x\n",flags);
-    }
-
-    ret = CombineRgn( newRgn, dc->hClipRgn, newRgn, 
-                        (flags & CLIP_EXCLUDE) ? RGN_DIFF : RGN_AND );
-    if (ret != ERROR)
-    {
-        if (!(flags & CLIP_KEEPRGN)) DeleteObject( dc->hClipRgn );
-        dc->hClipRgn = newRgn;    
-        CLIPPING_UpdateGCRegion( dc );
-    }
-    else DeleteObject( newRgn );
-    return ret;
-}
-
-
-/***********************************************************************
  *           ExcludeClipRect    (GDI.21)
  */
 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
@@ -268,6 +219,7 @@
 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
                                 INT right, INT bottom )
 {
+    HRGN newRgn;
     INT ret;
     DC *dc = DC_GetDCUpdate( hdc );
     if (!dc) return ERROR;
@@ -276,13 +228,25 @@
 
     if(dc->funcs->pExcludeClipRect)
         ret = dc->funcs->pExcludeClipRect( dc->physDev, left, top, right, bottom );
-    else {
-        left   = XLPTODP( dc, left );
-	right  = XLPTODP( dc, right );
-	top    = YLPTODP( dc, top );
-	bottom = YLPTODP( dc, bottom );
+    else
+    {
+        left   = dc->DCOrgX + XLPTODP( dc, left );
+        right  = dc->DCOrgX + XLPTODP( dc, right );
+        top    = dc->DCOrgY + YLPTODP( dc, top );
+        bottom = dc->DCOrgY + YLPTODP( dc, bottom );
 
-	ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
+        if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) ret = ERROR;
+        else
+        {
+            if (!dc->hClipRgn)
+            {
+                dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
+                CombineRgn( dc->hClipRgn, dc->hVisRgn, 0, RGN_COPY );
+            }
+            ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_DIFF );
+            DeleteObject( newRgn );
+        }
+        if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
     }
     GDI_ReleaseObj( hdc );
     return ret;
@@ -313,13 +277,30 @@
 
     if(dc->funcs->pIntersectClipRect)
         ret = dc->funcs->pIntersectClipRect( dc->physDev, left, top, right, bottom );
-    else {
-        left   = XLPTODP( dc, left );
-	right  = XLPTODP( dc, right );
-	top    = YLPTODP( dc, top );
-	bottom = YLPTODP( dc, bottom );
+    else
+    {
+        left   = dc->DCOrgX + XLPTODP( dc, left );
+        right  = dc->DCOrgX + XLPTODP( dc, right );
+        top    = dc->DCOrgY + YLPTODP( dc, top );
+        bottom = dc->DCOrgY + YLPTODP( dc, bottom );
 
-	ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
+        if (!dc->hClipRgn)
+        {
+            dc->hClipRgn = CreateRectRgn( left, top, right, bottom );
+            ret = SIMPLEREGION;
+        }
+        else
+        {
+            HRGN newRgn;
+
+            if (!(newRgn = CreateRectRgn( left, top, right, bottom ))) ret = ERROR;
+            else
+            {
+                ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_AND );
+                DeleteObject( newRgn );
+            }
+        }
+        if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
     }
     GDI_ReleaseObj( hdc );
     return ret;
@@ -327,74 +308,30 @@
 
 
 /***********************************************************************
- *           CLIPPING_IntersectVisRect
- *
- * Helper function for {Intersect,Exclude}VisRect, can be called from
- * elsewhere (like ExtTextOut()) to skip redundant metafile update and
- * coordinate conversion.
- */
-INT CLIPPING_IntersectVisRect( DC * dc, INT left, INT top,
-                                 INT right, INT bottom,
-                                 BOOL exclude )
-{
-    HRGN tempRgn, newRgn;
-    INT ret;
-
-    left   += dc->DCOrgX;
-    right  += dc->DCOrgX;
-    top    += dc->DCOrgY;
-    bottom += dc->DCOrgY;
-
-    if (!(newRgn = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
-    if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
-    {
-        DeleteObject( newRgn );
-        return ERROR;
-    }
-    ret = CombineRgn( newRgn, dc->hVisRgn, tempRgn,
-                        exclude ? RGN_DIFF : RGN_AND );
-    DeleteObject( tempRgn );
-
-    if (ret != ERROR)
-    {
-        RGNOBJ *newObj  = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
-        if (newObj)
-        {
-            RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC);
-            if (prevObj)
-            {
-                newObj->header.hNext = prevObj->header.hNext;
-                GDI_ReleaseObj( dc->hVisRgn );
-            }
-            GDI_ReleaseObj( newRgn );
-        }
-        DeleteObject( dc->hVisRgn );
-        dc->hVisRgn = newRgn;    
-        CLIPPING_UpdateGCRegion( dc );
-    }
-    else DeleteObject( newRgn );
-    return ret;
-}
-
-
-/***********************************************************************
  *           ExcludeVisRect    (GDI.73)
  */
 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
                              INT16 right, INT16 bottom )
 {
+    HRGN tempRgn;
     INT16 ret;
     DC * dc = DC_GetDCUpdate( hdc );
-    if (!dc) return ERROR;    
+    if (!dc) return ERROR;
 
-    left   = XLPTODP( dc, left );
-    right  = XLPTODP( dc, right );
-    top    = YLPTODP( dc, top );
-    bottom = YLPTODP( dc, bottom );
+    left   = dc->DCOrgX + XLPTODP( dc, left );
+    right  = dc->DCOrgX + XLPTODP( dc, right );
+    top    = dc->DCOrgY + YLPTODP( dc, top );
+    bottom = dc->DCOrgY + YLPTODP( dc, bottom );
 
     TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
 
-    ret = CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
+    if (!(tempRgn = CreateRectRgn( left, top, right, bottom ))) ret = ERROR;
+    else
+    {
+        ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_DIFF );
+        DeleteObject( tempRgn );
+    }
+    if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
     GDI_ReleaseObj( hdc );
     return ret;
 }
@@ -406,18 +343,25 @@
 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
                                INT16 right, INT16 bottom )
 {
+    HRGN tempRgn;
     INT16 ret;
     DC * dc = DC_GetDCUpdate( hdc );
-    if (!dc) return ERROR;    
+    if (!dc) return ERROR;
 
-    left   = XLPTODP( dc, left );
-    right  = XLPTODP( dc, right );
-    top    = YLPTODP( dc, top );
-    bottom = YLPTODP( dc, bottom );
+    left   = dc->DCOrgX + XLPTODP( dc, left );
+    right  = dc->DCOrgX + XLPTODP( dc, right );
+    top    = dc->DCOrgY + YLPTODP( dc, top );
+    bottom = dc->DCOrgY + YLPTODP( dc, bottom );
 
     TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
 
-    ret = CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
+    if (!(tempRgn = CreateRectRgn( left, top, right, bottom ))) ret = ERROR;
+    else
+    {
+        ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_AND );
+        DeleteObject( tempRgn );
+    }
+    if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
     GDI_ReleaseObj( hdc );
     return ret;
 }
@@ -562,13 +506,13 @@
 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
 {
     HRGN copy;
-    RGNOBJ *obj, *copyObj;
+    GDIOBJHDR *obj, *copyObj;
     DC *dc = DC_GetDCUpdate( hdc );
 
     if (!dc) return 0;
     TRACE("%04x\n", hdc );
 
-    if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC )))
+    if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC )))
     {
         GDI_ReleaseObj( hdc );
 	return 0;
@@ -580,15 +524,15 @@
         return 0;
     }  
     CombineRgn( copy, dc->hVisRgn, 0, RGN_COPY );
-    if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
+    if (!(copyObj = GDI_GetObjPtr( copy, REGION_MAGIC )))
     {
         DeleteObject( copy );
         GDI_ReleaseObj( dc->hVisRgn );
         GDI_ReleaseObj( hdc );
 	return 0;
     }
-    copyObj->header.hNext = obj->header.hNext;
-    obj->header.hNext = copy;
+    copyObj->hNext = obj->hNext;
+    obj->hNext = copy;
     GDI_ReleaseObj( copy );
     GDI_ReleaseObj( dc->hVisRgn );
     GDI_ReleaseObj( hdc );
@@ -602,25 +546,27 @@
 INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
 {
     HRGN saved;
-    RGNOBJ *obj, *savedObj;
+    GDIOBJHDR *obj, *savedObj;
     DC *dc = DC_GetDCPtr( hdc );
     INT16 ret = ERROR;
 
-    if (!dc) return ERROR;    
-    if (!dc->hVisRgn) goto done;
+    if (!dc) return ERROR;
+
     TRACE("%04x\n", hdc );
-    if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC ))) goto done;
 
-    saved = obj->header.hNext;
+    if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC ))) goto done;
+    saved = obj->hNext;
+
+    if ((savedObj = GDI_GetObjPtr( saved, REGION_MAGIC )))
+    {
+        ret = CombineRgn( dc->hVisRgn, saved, 0, RGN_COPY );
+        obj->hNext = savedObj->hNext;
+        GDI_ReleaseObj( saved );
+        DeleteObject( saved );
+        dc->flags &= ~DC_DIRTY;
+        CLIPPING_UpdateGCRegion( dc );
+    }
     GDI_ReleaseObj( dc->hVisRgn );
-    if (!saved || !(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC ))) goto done;
-
-    DeleteObject( dc->hVisRgn );
-    dc->hVisRgn = saved;
-    dc->flags &= ~DC_DIRTY;
-    CLIPPING_UpdateGCRegion( dc );
-    ret = savedObj->rgn->type; /* FIXME */
-    GDI_ReleaseObj( saved );
  done:
     GDI_ReleaseObj( hdc );
     return ret;
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index 9d464dd..dbdb945 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -897,7 +897,7 @@
       case FONT_MAGIC:    return FONT_DeleteObject( obj, (FONTOBJ*)header );
       case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
       case BITMAP_MAGIC:  return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
-      case REGION_MAGIC:  return REGION_DeleteObject( obj, (RGNOBJ*)header );
+      case REGION_MAGIC:  return REGION_DeleteObject( obj, (struct _RGNOBJ*)header );
       case DC_MAGIC:
           GDI_ReleaseObj( obj );
           return DeleteDC(obj);
diff --git a/objects/region.c b/objects/region.c
index 60b3f6e..102ddd8 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -104,6 +104,21 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(region);
 
+typedef struct {
+    INT size;
+    INT numRects;
+    RECT *rects;
+    RECT extents;
+} WINEREGION;
+
+  /* GDI logical region object */
+typedef struct _RGNOBJ
+{
+    GDIOBJHDR   header;
+    WINEREGION  *rgn;
+} RGNOBJ;
+
+
 /*  1 if two RECTs overlap.
  *  0 if two RECTs do not overlap.
  */
@@ -134,7 +149,6 @@
     (pReg)->numRects = 0; \
     (pReg)->extents.left = (pReg)->extents.top = 0; \
     (pReg)->extents.right = (pReg)->extents.bottom = 0; \
-    (pReg)->type = NULLREGION; \
  }
 
 #define REGION_NOT_EMPTY(pReg) pReg->numRects
@@ -423,6 +437,21 @@
 
 #define RGN_DEFAULT_RECTS	2
 
+
+/***********************************************************************
+ *            get_region_type
+ */
+inline static INT get_region_type( const RGNOBJ *obj )
+{
+    switch(obj->rgn->numRects)
+    {
+    case 0:  return NULLREGION;
+    case 1:  return SIMPLEREGION;
+    default: return COMPLEXREGION;
+    }
+}
+
+
 /***********************************************************************
  *            REGION_DumpRegion
  *            Outputs the contents of a WINEREGION
@@ -542,7 +571,7 @@
 	    obj->rgn->extents.bottom += y;
 	}
     }
-    ret = obj->rgn->type;
+    ret = get_region_type( obj );
     GDI_ReleaseObj( hrgn );
     return ret;
 }
@@ -573,7 +602,7 @@
 	rect->top = obj->rgn->extents.top;
 	rect->right = obj->rgn->extents.right;
 	rect->bottom = obj->rgn->extents.bottom;
-	ret = obj->rgn->type;
+	ret = get_region_type( obj );
 	GDI_ReleaseObj(hrgn);
 	return ret;
     }
@@ -671,8 +700,7 @@
         obj->rgn->rects->top = obj->rgn->extents.top = top;
         obj->rgn->rects->right = obj->rgn->extents.right = right;
         obj->rgn->rects->bottom = obj->rgn->extents.bottom = bottom;
-	obj->rgn->numRects = 1;
-	obj->rgn->type = SIMPLEREGION;
+        obj->rgn->numRects = 1;
     }
     else
 	EMPTY_REGION(obj->rgn);
@@ -804,7 +832,6 @@
 	rect.bottom = bottom;
 	REGION_UnionRectWithRegion( &rect, obj->rgn );
     }
-    obj->rgn->type = SIMPLEREGION; /* FIXME? */
     GDI_ReleaseObj( hrgn );
     return hrgn;
 }
@@ -1091,10 +1118,10 @@
     }
     return ret;
 }
+
 /***********************************************************************
  *           REGION_UnionRectWithRegion
  *           Adds a rectangle to a WINEREGION
- *           See below for REGION_UnionRectWithRgn
  */
 static void REGION_UnionRectWithRegion(const RECT *rect, WINEREGION *rgn)
 {
@@ -1103,26 +1130,10 @@
     region.rects = &region.extents;
     region.numRects = 1;
     region.size = 1;
-    region.type = SIMPLEREGION;
     region.extents = *rect;
     REGION_UnionRegion(rgn, rgn, &region);
-    return;
 }
 
-/***********************************************************************
- *           REGION_UnionRectWithRgn
- *           Adds a rectangle to a HRGN
- *           A helper used by scroll.c
- */
-BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect )
-{
-    RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
-
-    if(!obj) return FALSE;
-    REGION_UnionRectWithRegion( lpRect, obj->rgn );
-    GDI_ReleaseObj(hrgn);
-    return TRUE;
-}
 
 /***********************************************************************
  *           REGION_CreateFrameRgn
@@ -1163,66 +1174,7 @@
     return bRet;
 }
 
-/***********************************************************************
- *           REGION_LPTODP
- *
- * Convert region to device co-ords for the supplied dc. 
- */
-BOOL REGION_LPTODP( HDC hdc, HRGN hDest, HRGN hSrc )
-{
-    RECT *pCurRect, *pEndRect;
-    RGNOBJ *srcObj, *destObj;
-    DC * dc = DC_GetDCPtr( hdc );
-    RECT tmpRect;
-    BOOL ret = FALSE;
 
-    TRACE(" hdc=%04x dest=%04x src=%04x\n",
-	  hdc, hDest, hSrc) ;
-    if (!dc) return ret;
-    
-    if (dc->MapMode == MM_TEXT) /* Requires only a translation */
-    {
-        if( CombineRgn( hDest, hSrc, 0, RGN_COPY ) == ERROR ) goto done;
-	OffsetRgn( hDest, dc->vportOrgX - dc->wndOrgX, 
-		     dc->vportOrgY - dc->wndOrgY );
-	ret = TRUE;
-        goto done;
-    }
-
-    if(!( srcObj = (RGNOBJ *) GDI_GetObjPtr( hSrc, REGION_MAGIC) ))
-        goto done;
-    if(!( destObj = (RGNOBJ *) GDI_GetObjPtr( hDest, REGION_MAGIC) ))
-    {
-        GDI_ReleaseObj( hSrc );
-        goto done;
-    }
-    EMPTY_REGION( destObj->rgn );
-
-    pEndRect = srcObj->rgn->rects + srcObj->rgn->numRects;
-    for(pCurRect = srcObj->rgn->rects; pCurRect < pEndRect; pCurRect++)
-    {
-        tmpRect = *pCurRect;
-	tmpRect.left = XLPTODP( dc, tmpRect.left );
-	tmpRect.top = YLPTODP( dc, tmpRect.top );
-	tmpRect.right = XLPTODP( dc, tmpRect.right );
-	tmpRect.bottom = YLPTODP( dc, tmpRect.bottom );
-
-        if (tmpRect.left > tmpRect.right) 
-        { INT tmp = tmpRect.left; tmpRect.left = tmpRect.right; tmpRect.right = tmp; }
-        if (tmpRect.top > tmpRect.bottom) 
-        { INT tmp = tmpRect.top; tmpRect.top = tmpRect.bottom; tmpRect.bottom = tmp; }
-
-	REGION_UnionRectWithRegion( &tmpRect, destObj->rgn );
-    }
-    ret = TRUE;
-    
-    GDI_ReleaseObj( hDest );
-    GDI_ReleaseObj( hSrc );
- done:
-    GDI_ReleaseObj( hdc );
-    return ret;
-}
-    
 /***********************************************************************
  *           CombineRgn    (GDI.47)
  */
@@ -1256,7 +1208,7 @@
 	    if (mode == RGN_COPY)
 	    {
 		REGION_CopyRegion( destObj->rgn, src1Obj->rgn );
-		result = destObj->rgn->type;
+		result = get_region_type( destObj );
 	    }
 	    else
 	    {
@@ -1282,7 +1234,7 @@
 			REGION_SubtractRegion( destObj->rgn, src1Obj->rgn, src2Obj->rgn );
 			break;
 		    }
-		    result = destObj->rgn->type;
+		    result = get_region_type( destObj );
 		    GDI_ReleaseObj( hSrc2 );
 		}
 	    }
@@ -1361,8 +1313,6 @@
 	dst->extents.top = src->extents.top;
 	dst->extents.right = src->extents.right;
 	dst->extents.bottom = src->extents.bottom;
-	dst->type = src->type;
-
 	memcpy((char *) dst->rects, (char *) src->rects,
 	       (int) (src->numRects * sizeof(RECT)));
     }
@@ -1892,10 +1842,6 @@
      * due to coalescing, so we have to examine fewer rectangles.
      */
     REGION_SetExtents(newReg);
-    newReg->type = (newReg->numRects) ?
-                       ((newReg->numRects > 1) ? COMPLEXREGION : SIMPLEREGION)
-                       : NULLREGION ;
-    return;
 }
 
 /***********************************************************************
@@ -2071,10 +2017,6 @@
     newReg->extents.top = min(reg1->extents.top, reg2->extents.top);
     newReg->extents.right = max(reg1->extents.right, reg2->extents.right);
     newReg->extents.bottom = max(reg1->extents.bottom, reg2->extents.bottom);
-    newReg->type = (newReg->numRects) ?
-                        ((newReg->numRects > 1) ? COMPLEXREGION : SIMPLEREGION)
-                        : NULLREGION ;
-    return;
 }
 
 /***********************************************************************
@@ -2279,10 +2221,6 @@
      * due to coalescing, so we have to examine fewer rectangles.
      */
     REGION_SetExtents (regD);
-    regD->type = (regD->numRects) ?
-                       ((regD->numRects > 1) ? COMPLEXREGION : SIMPLEREGION)
-                       : NULLREGION ;
-    return;
 }
 
 /***********************************************************************
@@ -2876,9 +2814,6 @@
     }
     REGION_FreeStorage(SLLBlock.next);	
     REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
-    region->type = (region->numRects) ?
-                        ((region->numRects > 1) ? COMPLEXREGION : SIMPLEREGION)
-                        : NULLREGION;
 
     for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
 	tmpPtBlock = curPtBlock->next;
@@ -3120,8 +3055,6 @@
 	rgnDst->extents.top = rgnDst->rects[0].top;
 	rgnDst->extents.bottom = rgnDst->rects[j].bottom;
 
-	rgnDst->type = (j >= 1) ? COMPLEXREGION : SIMPLEREGION;
-
 	if( TRACE_ON(region) )
 	{
 	    TRACE("result:\n");
diff --git a/windows/dce.c b/windows/dce.c
index b55c12b..4d0d41c 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -35,7 +35,6 @@
 #include "dce.h"
 #include "win.h"
 #include "gdi.h"
-#include "region.h"
 #include "user.h"
 #include "wine/debug.h"
 #include "windef.h"
diff --git a/windows/winpos.c b/windows/winpos.c
index e40840d..f17959a 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -28,7 +28,6 @@
 #include "wine/server.h"
 #include "controls.h"
 #include "user.h"
-#include "region.h"
 #include "win.h"
 #include "hook.h"
 #include "message.h"