Fixed some bugs.
[reactos.git] / reactos / subsys / win32k / ntuser / windc.c
index fc8151e..1d5ace5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: windc.c,v 1.1 2002/07/04 20:12:27 dwelch Exp $
+/* $Id: windc.c,v 1.2 2002/07/17 21:04:57 dwelch Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
 #include <include/error.h>
 #include <include/winsta.h>
 #include <include/msgqueue.h>
+#include <include/window.h>
+#include <include/rect.h>
 
 #define NDEBUG
 #include <debug.h>
 
 /* FUNCTIONS *****************************************************************/
 
+BOOL STATIC
+DceGetVisRect(PWINDOW_OBJECT Window, BOOL ClientArea, RECT* Rect)
+{
+  if (ClientArea)
+    {
+      *Rect = Window->ClientRect;
+    }
+  else
+    {
+      *Rect = Window->WindowRect;
+    }
+
+  if (Window->Style & WS_VISIBLE)
+    {
+      INT XOffset = Rect->left;
+      INT YOffset = Rect->top;
+
+      while ((Window = Window->Parent) != NULL)
+       {
+         if ((Window->Style & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE)
+           {
+             W32kSetEmptyRect(Rect);
+             return(FALSE);
+           }
+         XOffset += Window->ClientRect.left;
+         YOffset += Window->ClientRect.top;
+         W32kOffsetRect(Rect, Window->ClientRect.left, 
+                        Window->ClientRect.top);
+         if (Window->ClientRect.left >= Window->ClientRect.right ||
+             Window->ClientRect.top >= Window->ClientRect.bottom ||
+             Rect->left >= Window->ClientRect.right ||
+             Rect->right <= Window->ClientRect.left ||
+             Rect->top >= Window->ClientRect.bottom ||
+             Rect->bottom <= Window->ClientRect.top)
+           {
+             W32kSetEmptyRect(Rect);
+             return(FALSE);
+           }
+         Rect->left = max(Rect->left, Window->ClientRect.left);
+         Rect->right = min(Rect->right, Window->ClientRect.right);
+         Rect->top = max(Rect->top, Window->ClientRect.top);
+         Rect->bottom = min(Rect->bottom, Window->ClientRect.bottom);
+       }
+      W32kOffsetRect(Rect, -XOffset, -YOffset);
+      return(TRUE);
+    }
+  W32kSetEmptyRect(Rect);
+  return(FALSE);
+}
+
+BOOL
+DceAddClipRects(PWINDOW_OBJECT Parent, PWINDOW_OBJECT End, 
+               HRGN ClipRgn, PRECT Rect, INT XOffset, INT YOffset)
+{
+  PLIST_ENTRY ChildListEntry;
+  PWINDOW_OBJECT Child;
+  RECT Rect1;
+
+  ChildListEntry = Parent->ChildrenListHead.Flink;
+  while (ChildListEntry != &Parent->ChildrenListHead)
+    {
+      Child = CONTAINING_RECORD(ChildListEntry, WINDOW_OBJECT, 
+                               SiblingListEntry);
+      if (Child == End)
+       {
+         return(TRUE);
+       }
+      if (Child->Style & WS_VISIBLE)
+       {
+         Rect1.left = Child->WindowRect.left + XOffset;
+         Rect1.top = Child->WindowRect.top + YOffset;
+         Rect1.right = Child->WindowRect.right + XOffset;
+         Rect1.bottom = Child->WindowRect.bottom + YOffset;
+
+         if (W32kIntersectRect(&Rect1, &Rect1, Rect))
+           {
+             W32kUnionRectWithRgn(ClipRgn, &Rect1);
+           }
+       }
+      ChildListEntry = ChildListEntry->Flink;
+    }
+  return(FALSE);
+}
+
 HRGN 
 DceGetVisRgn(HWND hWnd, ULONG Flags, HWND hWndChild, ULONG CFlags)
 {
+  PWINDOW_OBJECT Window;
+  PWINDOW_OBJECT Child;
+  HRGN VisRgn;
+  RECT Rect;
+
+  Window = W32kGetWindowObject(hWnd);
+  Child = W32kGetWindowObject(hWndChild);
+
+  if (Window != NULL && DceGetVisRect(Window, !(Flags & DCX_WINDOW), &Rect))
+    {
+      if ((VisRgn = W32kCreateRectRgnIndirect(&Rect)) != NULL)
+       {
+         HRGN ClipRgn = W32kCreateRectRgn(0, 0, 0, 0);
+         INT XOffset, YOffset;
+
+         if (ClipRgn != NULL)
+           {
+             if (Flags & DCX_CLIPCHILDREN && 
+                 !IsListEmpty(&Window->ChildrenListHead))
+               {
+                 if (Flags & DCX_WINDOW)
+                   {
+                     XOffset = Window->ClientRect.left -
+                       Window->WindowRect.left;
+                     YOffset = Window->ClientRect.top -
+                       Window->WindowRect.top;
+                   }           
+                 else
+                   {
+                     XOffset = YOffset = 0;
+                   }
+                 DceAddClipRects(Window, NULL, ClipRgn, &Rect,
+                                 XOffset, YOffset);
+               }
+
+             if (CFlags & DCX_CLIPCHILDREN && Child &&
+                 !IsListEmpty(&Child->ChildrenListHead))
+               {
+                 if (Flags & DCX_WINDOW)
+                   {
+                     XOffset = Window->ClientRect.left -
+                       Window->WindowRect.left;
+                     YOffset = Window->ClientRect.top -
+                       Window->WindowRect.top;
+                   }
+                 else
+                   {
+                     XOffset = YOffset = 0;
+                   }
+
+                 XOffset += Child->ClientRect.left;
+                 YOffset += Child->ClientRect.top;
+
+                 DceAddClipRects(Child, NULL, ClipRgn, &Rect,
+                                 XOffset, YOffset);
+               }
+
+             if (Flags & DCX_WINDOW)
+               {
+                 XOffset = -Window->WindowRect.left;
+                 YOffset = -Window->WindowRect.top;
+               }
+             else
+               {
+                 XOffset = -Window->ClientRect.left;
+                 YOffset = -Window->ClientRect.top;
+               }
+
+             if (Flags & DCX_CLIPSIBLINGS && Window->Parent != NULL)
+               {
+                 DceAddClipRects(Window->Parent, Window, ClipRgn,
+                                 &Rect, XOffset, YOffset);
+               }
+             
+             while (Window->Style & WS_CHILD)
+               {
+                 Window = Window->Parent;
+                 XOffset -= Window->ClientRect.left;
+                 YOffset -= Window->ClientRect.top;
+                 if (Window->Style & WS_CLIPSIBLINGS && 
+                     Window->Parent != NULL)
+                   {
+                     DceAddClipRects(Window->Parent, Window, ClipRgn,
+                                     &Rect, XOffset, YOffset);
+                   }
+               }
 
+             W32kCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
+             W32kDeleteObject(ClipRgn);
+           }
+         else
+           {
+             W32kDeleteObject(VisRgn);
+             VisRgn = 0;
+           }
+       }
+    }
+  else
+    {
+      VisRgn = W32kCreateRectRgn(0, 0, 0, 0);
+    }
+  W32kReleaseWindowObject(Window);
+  W32kReleaseWindowObject(Child);
+  return(VisRgn);
 }
 
 INT STDCALL